New feature: give access permission of networks to other accounts in same domain (#5769)

* Enhancement: create Shared networks and VPC private gateways by users

* UI bug fix: pass correct domainid in CreateSharedNetworkForm

* Update #5730: fix test failure with test_guest_vlan_range.py

* Update #5730: fix test failure with test_persistent_network.py

* Update #5730: Add since to new API commands and API parameters

* Update #5730: Get first physical network for VPC private gateway if other ways do not work

* Update #5730: code optimization (return !offering.isSpecifyVlan())

* Update #5730: fix hard-coded network offering id in test_pvlan.py

* Update #5730: skip access check on the network owner if the owner is ROOT/system

* Update #5730: overlap check on cidr/startip/endip

* Update #5730: add methods to get accountid/domainid of shared networks

* Update #5730: improve integration tests

* Update #5730: update as per GutoVeronezi's comments

* Network Sharing: give network access permission to other accounts within a domain

* network: update ip in lb/pf/dnat tables when update vm nic ip

* Update #5757: create 3 separated methods for DNAT/LB/PF update

* travis: install python3-setuptools

* Network Sharing: update integration test

* Update #5769: Remove NetworkPermission.Ops

* Update #5769: Update as per Daan's comments

* Update #5769: Update as per Suresh's comments

* Update #5769: fix UI bug that accounts/projects are not listed

* Update #5769: fix domain admin can deploy vm on L2 network of other users

* Update #5769: Remove method listPermittedNetworkIdsByDomains in NetworkPermissionDao

* Update #5769: Skip network operation permissions check for root admin

* UI: fix create Isolated/L2 network form

* Update #5730: fix create Shared network form

* Update #5769: fix domain admin can deploy vm on L2 network of other users

* test: fix test_storage_policy.py

* Update #5769: fix remove_nic in test_network_permissions.py

* Update #5769: extract some codes to a method

* Update #5769: fix add/remove nic by domain admin

* Update #5769: allow domain admin to enable/disable static nat and create port forwarding rules

* Update #5769: update integration test

* Update #5769: fix unit test AssignLoadBalancerTest.java

* Update #5769: allow normal users to share network permission to other users on UI

* Update #5769: fix small UI bug with label

* Update #5769: Support L2 network as associated network

* test: sleep 30s after restarting mgt server in test_kubernetes_supported_versions.py to fix test failures with test_secondary_storage.py

* Update #5784: revert part of changes in #2420

* Update #5757: invert if condition to reduce code indentation

* Update #5769: fix regular user cannot create L2 network

* Update #5769: Add associated nework id and name in private gateway response

* Update #5769: list networks by networkfilter=Account on UI

* Update #5769: fix ui issue when list private gateways or create shared network if no isolated networks

* Update #5769: fix vue ui warnings

* Update #5679: add BaseResponseWithAssociatedNetwork and extract method setResponseAssociatedNetworkInformation

* Update #5679: extract some methods in VpcManagerImpl.java

* Update #5679: Update smoke tests as per Daan's comments

* Update #5769: fix vpc with private gateways cannot be removed when remove an acount

* Update #5769: fix unit test failures after merging latest main

* Update #5769: fix schema-41610to41700.sql

* Update #5769: fix Request failed due to empty network offering list on UI

* Update #5769: Throw exception when account is not found by name

* Update #5769: display a warning message if network offering list is empty

* Update #5769: fix an UI bug caused by previous commit b286cb7677

* Update #5769: fix UI bugs due to vue3 merge

* Update #5769: fix issue due to account type refactoring

* Update #5769: fix ui bugs due to vue3

* Update #5769: fix issue due to vue3 upgrade

* Update #5769: fix issue due to vue3 upgrade part 2

* Update #5769: fix issue due to vue3 upgrade part 3

* Update #5769: highlight default scope when create shared network on UI

* Update #5769: fix domain list is not loaded on UI

* Update #5769: fix restart/delete shared network by normal users

* Update #5769: fix restart domain-scope shared network by domain admin

* Update #5769: fix 3 UI bugs (1) double networks in list; (2) icon of first items in list; (3) account/project autoselect

* Update #5769: fix 2 ui bugs; (1) selected project is not changed when change domain; (2) no network should be selected by default

* Update #5769: fix update shared networks by domain admin/regular user

* Update #5769: fix Flicking warning message about the empty network offerings

* Update #5769: display associated network name in shared network info card

* Update #5769: fix create private gateway form

* Update #5769: fix network lists in project view

* Update #5769: fix duplicated networks in network dropdown

* Update #5769: fix failed to create shared network if associated L2 network is Setup

* Update #5769: check AccessType.OperateEntry on network in its implementation

* Revert "Update #5769: check AccessType.OperateEntry on network in its implementation"

This reverts commit c42c489e5b.

* Update #5769: fix keyword search in list guest vlans
This commit is contained in:
Wei Zhou 2022-04-19 16:29:31 +02:00 committed by GitHub
parent 334891a4b9
commit a5014a28a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
86 changed files with 5599 additions and 542 deletions

View File

@ -16,17 +16,26 @@
// under the License.
package com.cloud.network;
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
public interface GuestVlan extends InternalIdentity, Identity {
import java.util.Date;
public interface GuestVlan extends InternalIdentity {
@Override
public long getId();
public long getAccountId();
Date getTakenAt();
public String getGuestVlanRange();
String getVnet();
public long getPhysicalNetworkId();
String getReservationId();
Long getAccountId();
long getDataCenterId();
long getPhysicalNetworkId();
Long getAccountGuestVlanMapId();
}

View File

@ -0,0 +1,32 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.network;
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.api.InternalIdentity;
public interface GuestVlanRange extends InternalIdentity, Identity {
@Override
public long getId();
public long getAccountId();
public String getGuestVlanRange();
public long getPhysicalNetworkId();
}

View File

@ -332,6 +332,14 @@ public interface Network extends ControlledEntity, StateObject<Network.State>, I
}
}
public enum NetworkFilter {
Account, // return account networks that have been registered for or created by the calling user
Domain, // return domain networks that have been registered for or created by the calling user
AccountDomain, // return account and domain networks that have been registered for or created by the calling user
Shared, // including networks that have been granted to the calling user by another user
All // all networks (account, domain and shared)
}
public class IpAddresses {
private String ip4Address;
private String ip6Address;
@ -372,6 +380,8 @@ public interface Network extends ControlledEntity, StateObject<Network.State>, I
}
}
static final String AssociatedNetworkId = "AssociatedNetworkId";
String getName();
Mode getMode();

View File

@ -35,6 +35,7 @@ import com.cloud.network.Network.Service;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.element.NetworkElement;
import com.cloud.network.element.UserDataServiceProvider;
import com.cloud.network.router.VirtualRouter;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.NetworkOffering.Detail;
import com.cloud.user.Account;
@ -195,6 +196,10 @@ public interface NetworkModel {
void checkNetworkPermissions(Account owner, Network network);
void checkNetworkOperatePermissions(Account owner, Network network);
void checkRouterPermissions(Account owner, VirtualRouter router);
String getDefaultManagementTrafficLabel(long zoneId, HypervisorType hypervisorType);
String getDefaultStorageTrafficLabel(long zoneId, HypervisorType hypervisorType);

View File

@ -0,0 +1,26 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.network;
import org.apache.cloudstack.api.InternalIdentity;
public interface NetworkPermission extends InternalIdentity {
long getNetworkId();
long getAccountId();
}

View File

@ -22,9 +22,14 @@ import java.util.Map;
import org.apache.cloudstack.api.command.admin.address.ReleasePodIpCmdByAdmin;
import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd;
import org.apache.cloudstack.api.command.admin.network.ListDedicatedGuestVlanRangesCmd;
import org.apache.cloudstack.api.command.admin.network.ListGuestVlansCmd;
import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd;
import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd;
import org.apache.cloudstack.api.command.user.network.CreateNetworkPermissionsCmd;
import org.apache.cloudstack.api.command.user.network.ListNetworkPermissionsCmd;
import org.apache.cloudstack.api.command.user.network.ListNetworksCmd;
import org.apache.cloudstack.api.command.user.network.RemoveNetworkPermissionsCmd;
import org.apache.cloudstack.api.command.user.network.ResetNetworkPermissionsCmd;
import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd;
import org.apache.cloudstack.api.command.user.network.UpdateNetworkCmd;
import org.apache.cloudstack.api.command.user.vm.ListNicsCmd;
@ -148,9 +153,9 @@ public interface NetworkService {
boolean deletePhysicalNetworkTrafficType(Long id);
GuestVlan dedicateGuestVlanRange(DedicateGuestVlanRangeCmd cmd);
GuestVlanRange dedicateGuestVlanRange(DedicateGuestVlanRangeCmd cmd);
Pair<List<? extends GuestVlan>, Integer> listDedicatedGuestVlanRanges(ListDedicatedGuestVlanRangesCmd cmd);
Pair<List<? extends GuestVlanRange>, Integer> listDedicatedGuestVlanRanges(ListDedicatedGuestVlanRangesCmd cmd);
boolean releaseDedicatedGuestVlanRange(Long dedicatedGuestVlanRangeId);
@ -184,7 +189,7 @@ public interface NetworkService {
* @throws ResourceAllocationException
*/
Network createPrivateNetwork(String networkName, String displayText, long physicalNetworkId, String broadcastUri, String startIp, String endIP, String gateway,
String netmask, long networkOwnerId, Long vpcId, Boolean sourceNat, Long networkOfferingId, Boolean bypassVlanOverlapCheck) throws ResourceAllocationException, ConcurrentOperationException,
String netmask, long networkOwnerId, Long vpcId, Boolean sourceNat, Long networkOfferingId, Boolean bypassVlanOverlapCheck, Long associatedNetworkId) throws ResourceAllocationException, ConcurrentOperationException,
InsufficientCapacityException;
/**
@ -210,4 +215,14 @@ public interface NetworkService {
AcquirePodIpCmdResponse allocatePodIp(Account account, String zoneId, String podId) throws ResourceAllocationException, ConcurrentOperationException;
boolean releasePodIp(ReleasePodIpCmdByAdmin ip) throws CloudRuntimeException;
Pair<List<? extends GuestVlan>, Integer> listGuestVlans(ListGuestVlansCmd cmd);
List<? extends NetworkPermission> listNetworkPermissions(ListNetworkPermissionsCmd listNetworkPermissionsCmd);
boolean createNetworkPermissions(CreateNetworkPermissionsCmd createNetworkPermissionsCmd);
boolean removeNetworkPermissions(RemoveNetworkPermissionsCmd removeNetworkPermissionsCmd);
boolean resetNetworkPermissions(ResetNetworkPermissionsCmd resetNetworkPermissionsCmd);
}

View File

@ -19,6 +19,7 @@ package com.cloud.network.vpc;
import java.util.List;
import java.util.Map;
import org.apache.cloudstack.api.command.user.vpc.CreatePrivateGatewayCmd;
import org.apache.cloudstack.api.command.user.vpc.ListPrivateGatewaysCmd;
import org.apache.cloudstack.api.command.user.vpc.ListStaticRoutesCmd;
import org.apache.cloudstack.api.command.user.vpc.RestartVPCCmd;
@ -165,8 +166,7 @@ public interface VpcService {
* @throws ConcurrentOperationException
* @throws ResourceAllocationException
*/
public PrivateGateway createVpcPrivateGateway(long vpcId, Long physicalNetworkId, String vlan, String ipAddress, String gateway, String netmask, long gatewayOwnerId,
Long networkOfferingId, Boolean isSoruceNat, Long aclId, Boolean bypassVlanOverlapCheck) throws ResourceAllocationException, ConcurrentOperationException, InsufficientCapacityException;
public PrivateGateway createVpcPrivateGateway(CreatePrivateGatewayCmd command) throws ResourceAllocationException, ConcurrentOperationException, InsufficientCapacityException;
/**
* Applies VPC private gateway on the backend, so it becomes functional

View File

@ -48,6 +48,7 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity,
public final static String SystemManagementNetwork = "System-Management-Network";
public final static String SystemStorageNetwork = "System-Storage-Network";
public final static String SystemPrivateGatewayNetworkOffering = "System-Private-Gateway-Network-Offering";
public final static String SystemPrivateGatewayNetworkOfferingWithoutVlan = "System-Private-Gateway-Network-Offering-Without-Vlan";
public final static String DefaultSharedNetworkOfferingWithSGService = "DefaultSharedNetworkOfferingWithSGService";
public final static String QuickCloudNoServices = "QuickCloudNoServices";

View File

@ -21,6 +21,7 @@ public class ApiConstants {
public static final String ACCOUNTS = "accounts";
public static final String ACCOUNT_TYPE = "accounttype";
public static final String ACCOUNT_ID = "accountid";
public static final String ACCOUNT_IDS = "accountids";
public static final String ACCUMULATE = "accumulate";
public static final String ACTIVITY = "activity";
public static final String ADAPTER_TYPE = "adaptertype";
@ -422,6 +423,8 @@ public class ApiConstants {
public static final String ISOLATED_PVLAN = "isolatedpvlan";
public static final String ISOLATED_PVLAN_TYPE = "isolatedpvlantype";
public static final String ISOLATION_URI = "isolationuri";
public static final String IS_DEDICATED = "isdedicated";
public static final String TAKEN = "taken";
public static final String VM_AVAILABLE = "vmavailable";
public static final String VM_LIMIT = "vmlimit";
public static final String VM_TOTAL = "vmtotal";
@ -441,6 +444,7 @@ public class ApiConstants {
public static final String TIER_NETWORK_OFFERINGS = "tiernetworkofferings";
public static final String NETWORK_IDS = "networkids";
public static final String NETWORK_ID = "networkid";
public static final String NETWORK_FILTER = "networkfilter";
public static final String NIC_ID = "nicid";
public static final String SPECIFY_VLAN = "specifyvlan";
public static final String IS_DEFAULT = "isdefault";
@ -536,6 +540,7 @@ public class ApiConstants {
public static final String ISOLATION_METHOD = "isolationmethod";
public static final String ISOLATION_METHODS = "isolationmethods";
public static final String PHYSICAL_NETWORK_ID = "physicalnetworkid";
public static final String PHYSICAL_NETWORK_NAME = "physicalnetworkname";
public static final String DEST_PHYSICAL_NETWORK_ID = "destinationphysicalnetworkid";
public static final String ENABLE = "enable";
public static final String ENABLED = "enabled";
@ -572,6 +577,7 @@ public class ApiConstants {
public static final String FIREWALL_DEVICE_CAPACITY = "fwdevicecapacity";
public static final String FIREWALL_DEVICE_DEDICATED = "fwdevicededicated";
public static final String SERVICE = "service";
public static final String ASSOCIATED_NETWORK = "associatednetwork";
public static final String ASSOCIATED_NETWORK_ID = "associatednetworkid";
public static final String ASSOCIATED_NETWORK_NAME = "associatednetworkname";
public static final String SOURCE_NAT_SUPPORTED = "sourcenatsupported";

View File

@ -0,0 +1,40 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.api;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
public abstract class BaseResponseWithAssociatedNetwork extends BaseResponseWithAnnotations {
@SerializedName(ApiConstants.ASSOCIATED_NETWORK_ID)
@Param(description = "the ID of the Network associated with this private gateway")
private String associatedNetworkId;
@SerializedName(ApiConstants.ASSOCIATED_NETWORK)
@Param(description = "the name of the Network associated with this private gateway")
private String associatedNetworkName;
public void setAssociatedNetworkId(String associatedNetworkId) {
this.associatedNetworkId = associatedNetworkId;
}
public void setAssociatedNetworkName(String associatedNetworkName) {
this.associatedNetworkName = associatedNetworkName;
}
}

View File

@ -27,6 +27,8 @@ import com.cloud.utils.Pair;
import org.apache.cloudstack.api.response.DirectDownloadCertificateResponse;
import org.apache.cloudstack.api.response.ResourceIconResponse;
import org.apache.cloudstack.api.response.DirectDownloadCertificateHostStatusResponse;
import org.apache.cloudstack.api.response.GuestVlanResponse;
import org.apache.cloudstack.api.response.NetworkPermissionsResponse;
import org.apache.cloudstack.api.response.RouterHealthCheckResultResponse;
import com.cloud.resource.RollingMaintenanceManager;
import org.apache.cloudstack.api.response.RollingMaintenanceResponse;
@ -154,9 +156,11 @@ import com.cloud.event.Event;
import com.cloud.host.Host;
import com.cloud.hypervisor.HypervisorCapabilities;
import com.cloud.network.GuestVlan;
import com.cloud.network.GuestVlanRange;
import com.cloud.network.IpAddress;
import com.cloud.network.Network;
import com.cloud.network.Network.Service;
import com.cloud.network.NetworkPermission;
import com.cloud.network.Networks.IsolationType;
import com.cloud.network.OvsProvider;
import com.cloud.network.PhysicalNetwork;
@ -262,7 +266,7 @@ public interface ResponseGenerator {
IPAddressResponse createIPAddressResponse(ResponseView view, IpAddress ipAddress);
GuestVlanRangeResponse createDedicatedGuestVlanRangeResponse(GuestVlan result);
GuestVlanRangeResponse createDedicatedGuestVlanRangeResponse(GuestVlanRange result);
GlobalLoadBalancerResponse createGlobalLoadBalancerResponse(GlobalLoadBalancerRule globalLoadBalancerRule);
@ -497,6 +501,10 @@ public interface ResponseGenerator {
ResourceIconResponse createResourceIconResponse(ResourceIcon resourceIcon);
GuestVlanResponse createGuestVlanResponse(GuestVlan vlan);
NetworkPermissionsResponse createNetworkPermissionsResponse(NetworkPermission permission);
DirectDownloadCertificateResponse createDirectDownloadCertificateResponse(DirectDownloadCertificate certificate);
List<DirectDownloadCertificateHostStatusResponse> createDirectDownloadCertificateHostMapResponse(List<DirectDownloadCertificateHostMap> hostMappings);

View File

@ -33,7 +33,7 @@ import org.apache.cloudstack.api.response.ProjectResponse;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.GuestVlan;
import com.cloud.network.GuestVlanRange;
import com.cloud.user.Account;
@APICommand(name = "dedicateGuestVlanRange", description = "Dedicates a guest vlan range to an account", responseObject = GuestVlanRangeResponse.class,
@ -106,7 +106,7 @@ public class DedicateGuestVlanRangeCmd extends BaseCmd {
@Override
public void execute() throws ResourceUnavailableException, ResourceAllocationException {
GuestVlan result = _networkService.dedicateGuestVlanRange(this);
GuestVlanRange result = _networkService.dedicateGuestVlanRange(this);
if (result != null) {
GuestVlanRangeResponse response = _responseGenerator.createDedicatedGuestVlanRangeResponse(result);
response.setResponseName(getCommandName());

View File

@ -32,7 +32,7 @@ import org.apache.cloudstack.api.response.PhysicalNetworkResponse;
import org.apache.cloudstack.api.response.ProjectResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import com.cloud.network.GuestVlan;
import com.cloud.network.GuestVlanRange;
import com.cloud.user.Account;
import com.cloud.utils.Pair;
@ -124,10 +124,10 @@ public class ListDedicatedGuestVlanRangesCmd extends BaseListCmd {
@Override
public void execute() {
Pair<List<? extends GuestVlan>, Integer> vlans = _networkService.listDedicatedGuestVlanRanges(this);
Pair<List<? extends GuestVlanRange>, Integer> vlans = _networkService.listDedicatedGuestVlanRanges(this);
ListResponse<GuestVlanRangeResponse> response = new ListResponse<GuestVlanRangeResponse>();
List<GuestVlanRangeResponse> guestVlanResponses = new ArrayList<GuestVlanRangeResponse>();
for (GuestVlan vlan : vlans.first()) {
for (GuestVlanRange vlan : vlans.first()) {
GuestVlanRangeResponse guestVlanResponse = _responseGenerator.createDedicatedGuestVlanRangeResponse(vlan);
guestVlanResponse.setObjectName("dedicatedguestvlanrange");
guestVlanResponses.add(guestVlanResponse);

View File

@ -0,0 +1,113 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.api.command.admin.network;
import java.util.ArrayList;
import java.util.List;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.response.PhysicalNetworkResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.log4j.Logger;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseListCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.GuestVlanResponse;
import org.apache.cloudstack.api.response.ListResponse;
import com.cloud.network.GuestVlan;
import com.cloud.utils.Pair;
@APICommand(name = "listGuestVlans", description = "Lists all guest vlans", responseObject = GuestVlanResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
since = "4.17.0",
authorized = {RoleType.Admin})
public class ListGuestVlansCmd extends BaseListCmd {
public static final Logger s_logger = Logger.getLogger(ListGuestVlansCmd.class.getName());
private static final String s_name = "listguestvlansresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.ID, type = CommandType.LONG, required = false, description = "list guest vlan by id")
private Long id;
@Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, required = false, description = "list guest vlan by zone")
private Long zoneId;
@Parameter(name = ApiConstants.PHYSICAL_NETWORK_ID, type = CommandType.UUID, entityType = PhysicalNetworkResponse.class, required = false, description = "list guest vlan by physical network")
private Long physicalNetworkId;
@Parameter(name = ApiConstants.VNET, type = CommandType.STRING, required = false, description = "list guest vlan by vnet")
private String vnet;
@Parameter(name = ApiConstants.ALLOCATED_ONLY, type = CommandType.BOOLEAN, required = false, description = "limits search results to allocated guest vlan. false by default.")
private Boolean allocatedOnly;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getId() {
return id;
}
public Long getZoneId() {
return zoneId;
}
public Long getPhysicalNetworkId() {
return physicalNetworkId;
}
public String getVnet() {
return vnet;
}
public Boolean getAllocatedOnly() {
return allocatedOnly;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public void execute() {
Pair<List<? extends GuestVlan>, Integer> vlans = _networkService.listGuestVlans(this);
ListResponse<GuestVlanResponse> response = new ListResponse<GuestVlanResponse>();
List<GuestVlanResponse> guestVlanResponses = new ArrayList<GuestVlanResponse>();
for (GuestVlan vlan : vlans.first()) {
GuestVlanResponse guestVlanResponse = _responseGenerator.createGuestVlanResponse(vlan);
guestVlanResponse.setObjectName("guestvlan");
guestVlanResponses.add(guestVlanResponse);
}
response.setResponses(guestVlanResponses, vlans.second());
response.setResponseName(getCommandName());
this.setResponseObject(response);
}
}

View File

@ -17,6 +17,8 @@
package org.apache.cloudstack.api.command.admin.network;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.apache.cloudstack.api.command.admin.AdminCmd;
import org.apache.cloudstack.api.command.user.network.ListNetworksCmd;
@ -26,4 +28,16 @@ import com.cloud.network.Network;
@APICommand(name = "listNetworks", description = "Lists all available networks.", responseObject = NetworkResponse.class, responseView = ResponseView.Full, entityType = {Network.class},
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class ListNetworksCmdByAdmin extends ListNetworksCmd implements AdminCmd {}
public class ListNetworksCmdByAdmin extends ListNetworksCmd implements AdminCmd {
@Parameter(name= ApiConstants.VLAN, type=CommandType.STRING, description="the ID or VID of the network", since = "4.17.0")
private String vlan;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public String getVlan() {
return vlan;
}
}

View File

@ -0,0 +1,74 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.api.command.admin.vpc;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.log4j.Logger;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.apache.cloudstack.api.command.admin.AdminCmd;
import org.apache.cloudstack.api.command.user.vpc.CreatePrivateGatewayCmd;
import org.apache.cloudstack.api.response.PhysicalNetworkResponse;
import org.apache.cloudstack.api.response.PrivateGatewayResponse;
import com.cloud.network.vpc.VpcGateway;
@APICommand(name = "createPrivateGateway", description = "Creates a private gateway",
responseObject = PrivateGatewayResponse.class,
responseView = ResponseView.Full,
entityType = {VpcGateway.class},
since = "4.17.0",
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class CreatePrivateGatewayByAdminCmd extends CreatePrivateGatewayCmd implements AdminCmd {
public static final Logger s_logger = Logger.getLogger(CreatePrivateGatewayByAdminCmd.class.getName());
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.PHYSICAL_NETWORK_ID,
type = CommandType.UUID,
entityType = PhysicalNetworkResponse.class,
description = "the Physical Network ID the network belongs to")
private Long physicalNetworkId;
@Parameter(name = ApiConstants.VLAN, type = CommandType.STRING, description = "the network implementation uri for the private gateway")
private String broadcastUri;
@Parameter(name = ApiConstants.BYPASS_VLAN_OVERLAP_CHECK, type = CommandType.BOOLEAN, description = "when true bypasses VLAN id/range overlap check during private gateway creation")
private Boolean bypassVlanOverlapCheck;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public String getBroadcastUri() {
return broadcastUri;
}
public Long getPhysicalNetworkId() {
return physicalNetworkId;
}
public Boolean getBypassVlanOverlapCheck() {
return BooleanUtils.toBoolean(bypassVlanOverlapCheck);
}
}

View File

@ -18,6 +18,7 @@ package org.apache.cloudstack.api.command.admin.vpc;
import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants;
@ -37,7 +38,8 @@ import com.cloud.network.vpc.VpcGateway;
import com.cloud.user.Account;
@APICommand(name = "deletePrivateGateway", description = "Deletes a Private gateway", responseObject = SuccessResponse.class, entityType = {VpcGateway.class},
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
public class DeletePrivateGatewayCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger.getLogger(DeletePrivateGatewayCmd.class.getName());
private static final String s_name = "deleteprivategatewayresponse";

View File

@ -112,7 +112,7 @@ public class CreateNetworkCmd extends BaseCmd implements UserCmd {
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "account that will own the network")
private String accountName;
@Parameter(name = ApiConstants.PROJECT_ID, type = CommandType.UUID, entityType = ProjectResponse.class, description = "an optional project for the SSH key")
@Parameter(name = ApiConstants.PROJECT_ID, type = CommandType.UUID, entityType = ProjectResponse.class, description = "an optional project for the network")
private Long projectId;
@Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class, description = "domain ID of the account owning a network")
@ -150,6 +150,13 @@ public class CreateNetworkCmd extends BaseCmd implements UserCmd {
@Parameter(name = ApiConstants.ACL_ID, type = CommandType.UUID, entityType = NetworkACLResponse.class, description = "Network ACL ID associated for the network")
private Long aclId;
@Parameter(name = ApiConstants.ASSOCIATED_NETWORK_ID,
type = CommandType.UUID,
entityType = NetworkResponse.class,
since = "4.17.0",
description = "The network this network is associated to. only available if create a Shared network")
private Long associatedNetworkId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -225,6 +232,10 @@ public class CreateNetworkCmd extends BaseCmd implements UserCmd {
return isolatedPvlanType;
}
public Long getAssociatedNetworkId() {
return associatedNetworkId;
}
@Override
public boolean isDisplay() {
if(displayNetwork == null)
@ -249,11 +260,31 @@ public class CreateNetworkCmd extends BaseCmd implements UserCmd {
throw new InvalidParameterValueException("Unable to find network offering by ID " + networkOfferingId);
}
Network associatedNetwork = null;
if (associatedNetworkId != null) {
associatedNetwork = _entityMgr.findById(Network.class, associatedNetworkId);
if (associatedNetwork == null) {
throw new InvalidParameterValueException("Unable to find network by ID " + associatedNetworkId);
}
if (offering.getGuestType() != GuestType.Shared) {
throw new InvalidParameterValueException("Associated network ID can be specified for networks of guest IP type " + GuestType.Shared + " only.");
}
if (zoneId != null && associatedNetwork.getDataCenterId() != zoneId) {
throw new InvalidParameterValueException("The network can only be created in the same zone as the associated network");
} else if (zoneId == null) {
zoneId = associatedNetwork.getDataCenterId();
}
if (physicalNetworkId != null && !physicalNetworkId.equals(associatedNetwork.getPhysicalNetworkId())) {
throw new InvalidParameterValueException("The network can only be created on the same physical network as the associated network");
} else if (physicalNetworkId == null) {
physicalNetworkId = associatedNetwork.getPhysicalNetworkId();
}
}
if (physicalNetworkId != null) {
if (offering.getGuestType() == GuestType.Shared) {
return physicalNetworkId;
} else {
throw new InvalidParameterValueException("Physical network OD can be specified for networks of guest IP type " + GuestType.Shared + " only.");
throw new InvalidParameterValueException("Physical network ID can be specified for networks of guest IP type " + GuestType.Shared + " only.");
}
} else {
if (zoneId == null) {

View File

@ -0,0 +1,130 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.api.command.user.network;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.AccountResponse;
import org.apache.cloudstack.api.response.NetworkResponse;
import org.apache.cloudstack.api.response.ProjectResponse;
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.log4j.Logger;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.network.Network;
import com.cloud.user.Account;
import java.util.List;
@APICommand(name = CreateNetworkPermissionsCmd.APINAME, description = "Updates network permissions.",
responseObject = SuccessResponse.class,
entityType = {Network.class},
requestHasSensitiveInfo = false,
responseHasSensitiveInfo = false,
since = "4.17.0",
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
public class CreateNetworkPermissionsCmd extends BaseCmd {
public static final Logger LOGGER = Logger.getLogger(CreateNetworkPermissionsCmd.class.getName());
public static final String APINAME = "createNetworkPermissions";
// ///////////////////////////////////////////////////
// ////////////// API parameters /////////////////////
// ///////////////////////////////////////////////////
@Parameter(name = ApiConstants.ACCOUNTS,
type = CommandType.LIST,
collectionType = CommandType.STRING,
description = "a comma delimited list of accounts within owner's domain. If specified, \"op\" parameter has to be passed in.")
private List<String> accountNames;
@Parameter(name = ApiConstants.ACCOUNT_IDS,
type = CommandType.LIST,
collectionType = CommandType.UUID,
entityType = AccountResponse.class,
description = "a comma delimited list of account IDs within owner's domain. If specified, \"op\" parameter has to be passed in.")
private List<Long> accountIds;
@Parameter(name = ApiConstants.NETWORK_ID, type = CommandType.UUID, entityType = NetworkResponse.class, required = true, description = "the network ID")
private Long networkId;
@Parameter(name = ApiConstants.PROJECT_IDS,
type = CommandType.LIST,
collectionType = CommandType.UUID,
entityType = ProjectResponse.class,
description = "a comma delimited list of projects within owner's domain. If specified, \"op\" parameter has to be passed in.")
private List<Long> projectIds;
// ///////////////////////////////////////////////////
// ///////////////// Accessors ///////////////////////
// ///////////////////////////////////////////////////
public List<String> getAccountNames() {
return accountNames;
}
public List<Long> getAccountIds() {
return accountIds;
}
public Long getNetworkId() {
return networkId;
}
public List<Long> getProjectIds() {
return projectIds;
}
// ///////////////////////////////////////////////////
// ///////////// API Implementation///////////////////
// ///////////////////////////////////////////////////
@Override
public String getCommandName() {
return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
}
@Override
public void execute() {
if (accountIds != null && accountNames != null) {
throw new InvalidParameterValueException("Accounts and accountNames can't be specified together");
}
boolean result = _networkService.createNetworkPermissions(this);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update network permissions");
}
}
@Override
public long getEntityOwnerId() {
Network network = _entityMgr.findById(Network.class, getNetworkId());
if (network != null) {
return network.getAccountId();
}
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
}
}

View File

@ -16,12 +16,13 @@
// under the License.
package org.apache.cloudstack.api.command.user.network;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;

View File

@ -0,0 +1,94 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.api.command.user.network;
import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.command.user.UserCmd;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.NetworkPermissionsResponse;
import org.apache.cloudstack.api.response.NetworkResponse;
import com.cloud.network.Network;
import com.cloud.network.NetworkPermission;
import com.cloud.user.Account;
import java.util.ArrayList;
import java.util.List;
@APICommand(name = ListNetworkPermissionsCmd.APINAME, description = "List network visibility and all accounts that have permissions to view this network.",
responseObject = NetworkPermissionsResponse.class,
requestHasSensitiveInfo = false,
responseHasSensitiveInfo = false,
since = "4.17.0",
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
public class ListNetworkPermissionsCmd extends BaseCmd implements UserCmd {
public static final Logger LOGGER = Logger.getLogger(ListNetworkPermissionsCmd.class.getName());
public static final String APINAME = "listNetworkPermissions";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.NETWORK_ID, type = CommandType.UUID, entityType = NetworkResponse.class, required = true, description = "Lists network permission by network ID")
private Long networkId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public Long getNetworkId() {
return networkId;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public long getEntityOwnerId() {
Network Network = _entityMgr.findById(Network.class, getNetworkId());
if (Network != null) {
return Network.getAccountId();
}
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
}
@Override
public String getCommandName() {
return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
}
@Override
public void execute() {
List<? extends NetworkPermission> permissions = _networkService.listNetworkPermissions(this);
ListResponse<NetworkPermissionsResponse> response = new ListResponse<>();
List<NetworkPermissionsResponse> networkPermissionResponses = new ArrayList<>();
for (NetworkPermission permission : permissions) {
NetworkPermissionsResponse networkPermissionResponse = _responseGenerator.createNetworkPermissionsResponse(permission);
networkPermissionResponses.add(networkPermissionResponse);
}
response.setResponses(networkPermissionResponses, permissions.size());
response.setResponseName(getCommandName());
setResponseObject(response);
}
}

View File

@ -96,10 +96,28 @@ public class ListNetworksCmd extends BaseListTaggedResourcesCmd implements UserC
@Parameter(name = ApiConstants.NETWORK_OFFERING_ID, type = CommandType.UUID, entityType = NetworkOfferingResponse.class, description = "list networks by network offering ID")
private Long networkOfferingId;
@Parameter(name = ApiConstants.ASSOCIATED_NETWORK_ID,
type = CommandType.UUID,
entityType = NetworkResponse.class,
since = "4.17.0",
description = "List networks by associated networks. Only available if create a Shared network.")
private Long associatedNetworkId;
@Parameter(name = ApiConstants.SHOW_RESOURCE_ICON, type = CommandType.BOOLEAN,
description = "flag to display the resource icon for networks")
private Boolean showIcon;
@Parameter(name = ApiConstants.NETWORK_FILTER,
type = CommandType.STRING,
since = "4.17.0",
description = "possible values are \"account\", \"domain\", \"accountdomain\",\"shared\", and \"all\". Default value is \"all\"."
+ "* account : account networks that have been registered for or created by the calling user. "
+ "* domain : domain networks that have been registered for or created by the calling user. "
+ "* accountdomain : account and domain networks that have been registered for or created by the calling user. "
+ "* shared : networks that have been granted to the calling user by another user. "
+ "* all : all networks (account, domain and shared).")
private String networkFilter;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -166,6 +184,10 @@ public class ListNetworksCmd extends BaseListTaggedResourcesCmd implements UserC
return networkOfferingId;
}
public Long getAssociatedNetworkId() {
return associatedNetworkId;
}
@Override
public Boolean getDisplay() {
if (display != null) {
@ -178,6 +200,10 @@ public class ListNetworksCmd extends BaseListTaggedResourcesCmd implements UserC
return showIcon != null ? showIcon : false;
}
public String getNetworkFilter() {
return networkFilter;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -0,0 +1,129 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.api.command.user.network;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.AccountResponse;
import org.apache.cloudstack.api.response.NetworkResponse;
import org.apache.cloudstack.api.response.ProjectResponse;
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.log4j.Logger;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.network.Network;
import com.cloud.user.Account;
import java.util.List;
@APICommand(name = RemoveNetworkPermissionsCmd.APINAME, description = "Removes network permissions.",
responseObject = SuccessResponse.class,
entityType = {Network.class},
requestHasSensitiveInfo = false,
responseHasSensitiveInfo = false,
since = "4.17.0",
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
public class RemoveNetworkPermissionsCmd extends BaseCmd {
public static final Logger LOGGER = Logger.getLogger(RemoveNetworkPermissionsCmd.class.getName());
public static final String APINAME = "removeNetworkPermissions";
// ///////////////////////////////////////////////////
// ////////////// API parameters /////////////////////
// ///////////////////////////////////////////////////
@Parameter(name = ApiConstants.ACCOUNTS,
type = CommandType.LIST,
collectionType = CommandType.STRING,
description = "a comma delimited list of accounts within owner's domain. If specified, \"op\" parameter has to be passed in.")
private List<String> accountNames;
@Parameter(name = ApiConstants.ACCOUNT_IDS,
type = CommandType.LIST,
collectionType = CommandType.UUID,
entityType = AccountResponse.class,
description = "a comma delimited list of account IDs within owner's domain. If specified, \"op\" parameter has to be passed in.")
private List<Long> accountIds;
@Parameter(name = ApiConstants.NETWORK_ID, type = CommandType.UUID, entityType = NetworkResponse.class, required = true, description = "the network ID")
private Long networkId;
@Parameter(name = ApiConstants.PROJECT_IDS,
type = CommandType.LIST,
collectionType = CommandType.UUID,
entityType = ProjectResponse.class,
description = "a comma delimited list of projects within owner's domain. If specified, \"op\" parameter has to be passed in.")
private List<Long> projectIds;
// ///////////////////////////////////////////////////
// ///////////////// Accessors ///////////////////////
// ///////////////////////////////////////////////////
public List<String> getAccountNames() {
return accountNames;
}
public List<Long> getAccountIds() {
return accountIds;
}
public Long getNetworkId() {
return networkId;
}
public List<Long> getProjectIds() {
return projectIds;
}
// ///////////////////////////////////////////////////
// ///////////// API Implementation///////////////////
// ///////////////////////////////////////////////////
@Override
public String getCommandName() {
return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
}
@Override
public void execute() {
if (accountIds != null && accountNames != null) {
throw new InvalidParameterValueException("Accounts and accountNames can't be specified together");
}
boolean result = _networkService.removeNetworkPermissions(this);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update network permissions");
}
}
@Override
public long getEntityOwnerId() {
Network network = _entityMgr.findById(Network.class, getNetworkId());
if (network != null) {
return network.getAccountId();
}
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
}
}

View File

@ -0,0 +1,89 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.api.command.user.network;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.NetworkResponse;
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.log4j.Logger;
import com.cloud.network.Network;
import com.cloud.user.Account;
@APICommand(name = ResetNetworkPermissionsCmd.APINAME, description = "Resets network permissions.",
responseObject = SuccessResponse.class,
entityType = {Network.class},
requestHasSensitiveInfo = false,
responseHasSensitiveInfo = false,
since = "4.17.0",
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
public class ResetNetworkPermissionsCmd extends BaseCmd {
public static final Logger LOGGER = Logger.getLogger(ResetNetworkPermissionsCmd.class.getName());
public static final String APINAME = "resetNetworkPermissions";
// ///////////////////////////////////////////////////
// ////////////// API parameters /////////////////////
// ///////////////////////////////////////////////////
@Parameter(name = ApiConstants.NETWORK_ID, type = CommandType.UUID, entityType = NetworkResponse.class, required = true, description = "the network ID")
private Long networkId;
// ///////////////////////////////////////////////////
// ///////////////// Accessors ///////////////////////
// ///////////////////////////////////////////////////
public Long getNetworkId() {
return networkId;
}
// ///////////////////////////////////////////////////
// ///////////// API Implementation///////////////////
// ///////////////////////////////////////////////////
@Override
public String getCommandName() {
return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
}
@Override
public void execute() {
boolean result = _networkService.resetNetworkPermissions(this);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update network permissions");
}
}
@Override
public long getEntityOwnerId() {
Network network = _entityMgr.findById(Network.class, getNetworkId());
if (network != null) {
return network.getAccountId();
}
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
}
}

View File

@ -21,6 +21,7 @@ import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;
@ -124,6 +125,16 @@ public class RestartNetworkCmd extends BaseAsyncCmd {
return EventTypes.EVENT_NETWORK_RESTART;
}
@Override
public Long getInstanceId() {
return getNetworkId();
}
@Override
public ApiCommandJobType getInstanceType() {
return ApiCommandJobType.Network;
}
@Override
public long getEntityOwnerId() {
Network network = _networkService.getNetwork(id);

View File

@ -20,6 +20,7 @@ import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;
@ -144,6 +145,16 @@ public class UpdateNetworkCmd extends BaseAsyncCustomIdCmd implements UserCmd {
return s_name;
}
@Override
public Long getInstanceId() {
return getId();
}
@Override
public ApiCommandJobType getInstanceType() {
return ApiCommandJobType.Network;
}
@Override
public long getEntityOwnerId() {
Network network = _networkService.getNetwork(id);

View File

@ -14,10 +14,11 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.api.command.admin.vpc;
package org.apache.cloudstack.api.command.user.vpc;
import org.apache.log4j.Logger;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants;
@ -25,10 +26,12 @@ import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.BaseAsyncCreateCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.command.user.UserCmd;
import org.apache.cloudstack.api.response.NetworkACLResponse;
import org.apache.cloudstack.api.response.NetworkOfferingResponse;
import org.apache.cloudstack.api.response.PhysicalNetworkResponse;
import org.apache.cloudstack.api.response.NetworkResponse;
import org.apache.cloudstack.api.response.PrivateGatewayResponse;
import org.apache.cloudstack.api.response.VpcResponse;
@ -41,11 +44,14 @@ import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.vpc.PrivateGateway;
import com.cloud.network.vpc.Vpc;
import com.cloud.network.vpc.VpcGateway;
import com.cloud.user.Account;
@APICommand(name = "createPrivateGateway", description = "Creates a private gateway", responseObject = PrivateGatewayResponse.class, entityType = {VpcGateway.class},
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class CreatePrivateGatewayCmd extends BaseAsyncCreateCmd {
@APICommand(name = "createPrivateGateway", description = "Creates a private gateway",
responseObject = PrivateGatewayResponse.class,
responseView = ResponseView.Restricted,
entityType = {VpcGateway.class},
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})
public class CreatePrivateGatewayCmd extends BaseAsyncCreateCmd implements UserCmd {
public static final Logger s_logger = Logger.getLogger(CreatePrivateGatewayCmd.class.getName());
private static final String s_name = "createprivategatewayresponse";
@ -54,12 +60,6 @@ public class CreatePrivateGatewayCmd extends BaseAsyncCreateCmd {
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.PHYSICAL_NETWORK_ID,
type = CommandType.UUID,
entityType = PhysicalNetworkResponse.class,
description = "the Physical Network ID the network belongs to")
private Long physicalNetworkId;
@Parameter(name = ApiConstants.GATEWAY, type = CommandType.STRING, required = true, description = "the gateway of the Private gateway")
private String gateway;
@ -69,9 +69,6 @@ public class CreatePrivateGatewayCmd extends BaseAsyncCreateCmd {
@Parameter(name = ApiConstants.IP_ADDRESS, type = CommandType.STRING, required = true, description = "the IP address of the Private gateaway")
private String ipAddress;
@Parameter(name = ApiConstants.VLAN, type = CommandType.STRING, required = true, description = "the network implementation uri for the private gateway")
private String broadcastUri;
@Parameter(name = ApiConstants.NETWORK_OFFERING_ID,
type = CommandType.UUID,
required = false,
@ -92,8 +89,12 @@ public class CreatePrivateGatewayCmd extends BaseAsyncCreateCmd {
@Parameter(name = ApiConstants.ACL_ID, type = CommandType.UUID, entityType = NetworkACLResponse.class, required = false, description = "the ID of the network ACL")
private Long aclId;
@Parameter(name=ApiConstants.BYPASS_VLAN_OVERLAP_CHECK, type=CommandType.BOOLEAN, description="when true bypasses VLAN id/range overlap check during private gateway creation")
private Boolean bypassVlanOverlapCheck;
@Parameter(name = ApiConstants.ASSOCIATED_NETWORK_ID,
type = CommandType.UUID,
entityType = NetworkResponse.class,
since = "4.17.0",
description = "The isolated network this private gateway is associated to.")
private Long associatedNetworkId;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
@ -103,23 +104,15 @@ public class CreatePrivateGatewayCmd extends BaseAsyncCreateCmd {
return gateway;
}
public String getBroadcastUri() {
return broadcastUri;
}
public String getNetmask() {
return netmask;
}
public String getStartIp() {
public String getIpAddress() {
return ipAddress;
}
public Long getPhysicalNetworkId() {
return physicalNetworkId;
}
private Long getNetworkOfferingId() {
public Long getNetworkOfferingId() {
return networkOfferingId;
}
@ -138,11 +131,8 @@ public class CreatePrivateGatewayCmd extends BaseAsyncCreateCmd {
return aclId;
}
public Boolean getBypassVlanOverlapCheck() {
if (bypassVlanOverlapCheck != null) {
return bypassVlanOverlapCheck;
}
return false;
public Long getAssociatedNetworkId() {
return associatedNetworkId;
}
/////////////////////////////////////////////////////
@ -157,9 +147,7 @@ public class CreatePrivateGatewayCmd extends BaseAsyncCreateCmd {
public void create() throws ResourceAllocationException {
PrivateGateway result = null;
try {
result =
_vpcService.createVpcPrivateGateway(getVpcId(), getPhysicalNetworkId(), getBroadcastUri(), getStartIp(), getGateway(), getNetmask(), getEntityOwnerId(),
getNetworkOfferingId(), getIsSourceNat(), getAclId(), getBypassVlanOverlapCheck());
result = _vpcService.createVpcPrivateGateway(this);
} catch (InsufficientCapacityException ex) {
s_logger.info(ex);
s_logger.trace(ex);
@ -191,7 +179,11 @@ public class CreatePrivateGatewayCmd extends BaseAsyncCreateCmd {
@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM;
Vpc vpc = _entityMgr.findById(Vpc.class, vpcId);
if (vpc == null) {
throw new InvalidParameterValueException("Invalid id is specified for the vpc");
}
return vpc.getAccountId();
}
@Override

View File

@ -22,10 +22,10 @@ import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.EntityReference;
import com.cloud.network.GuestVlan;
import com.cloud.network.GuestVlanRange;
import com.cloud.serializer.Param;
@EntityReference(value = GuestVlan.class)
@EntityReference(value = GuestVlanRange.class)
@SuppressWarnings("unused")
public class GuestVlanRangeResponse extends BaseResponse implements ControlledEntityResponse {
@SerializedName(ApiConstants.ID)

View File

@ -0,0 +1,156 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.api.response;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import com.cloud.serializer.Param;
import java.util.Date;
import java.util.List;
@SuppressWarnings("unused")
public class GuestVlanResponse extends BaseResponse implements ControlledEntityResponse {
@SerializedName(ApiConstants.ID)
@Param(description = "the guest VLAN id")
private long id;
@SerializedName(ApiConstants.VLAN)
@Param(description = "the guest VLAN")
private String guestVlan;
@SerializedName(ApiConstants.ACCOUNT)
@Param(description = "the account of the guest VLAN range")
private String accountName;
@SerializedName(ApiConstants.DOMAIN_ID)
@Param(description = "the domain ID of the guest VLAN range")
private String domainId;
@SerializedName(ApiConstants.DOMAIN)
@Param(description = "the domain name of the guest VLAN range")
private String domainName;
@SerializedName(ApiConstants.PROJECT_ID)
@Param(description = "the project id of the guest VLAN range")
private String projectId;
@SerializedName(ApiConstants.PROJECT)
@Param(description = "the project name of the guest VLAN range")
private String projectName;
@SerializedName(ApiConstants.ZONE_ID)
@Param(description = "the zone ID of the guest VLAN range")
private String zoneId;
@SerializedName(ApiConstants.ZONE_NAME)
@Param(description = "the zone name of the guest VLAN range")
private String zoneName;
@SerializedName(ApiConstants.PHYSICAL_NETWORK_ID)
@Param(description = "the physical network ID of the guest VLAN range")
private String physicalNetworkId;
@SerializedName(ApiConstants.PHYSICAL_NETWORK_NAME)
@Param(description = "the physical network name of the guest VLAN range")
private String physicalNetworkName;
@SerializedName(ApiConstants.IS_DEDICATED)
@Param(description = "true if the guest VLAN is dedicated to the account")
private Boolean isDedicated;
@SerializedName(ApiConstants.ALLOCATION_STATE)
@Param(description = "the allocation state of the guest VLAN")
private String allocationState;
@SerializedName(ApiConstants.TAKEN)
@Param(description = "date the guest VLAN was taken")
private Date taken;
@SerializedName(ApiConstants.NETWORK)
@Param(description = "the list of networks who use this guest VLAN", responseObject = NetworkResponse.class)
private List<NetworkResponse> networks;
public void setId(long id) {
this.id = id;
}
@Override
public void setAccountName(String accountName) {
this.accountName = accountName;
}
@Override
public void setDomainId(String domainId) {
this.domainId = domainId;
}
@Override
public void setDomainName(String domainName) {
this.domainName = domainName;
}
@Override
public void setProjectId(String projectId) {
this.projectId = projectId;
}
@Override
public void setProjectName(String projectName) {
this.projectName = projectName;
}
public void setZoneId(String zoneId) {
this.zoneId = zoneId;
}
public void setZoneName(String zoneName) {
this.zoneName = zoneName;
}
public void setPhysicalNetworkId(String physicalNetworkId) {
this.physicalNetworkId = physicalNetworkId;
}
public void setPhysicalNetworkName(String physicalNetworkName) {
this.physicalNetworkName = physicalNetworkName;
}
public void setGuestVlan(String guestVlan) {
this.guestVlan = guestVlan;
}
public void setDedicated(Boolean dedicated) {
isDedicated = dedicated;
}
public void setAllocationState(String allocationState) {
this.allocationState = allocationState;
}
public void setTaken(Date taken) {
this.taken = taken;
}
public void setNetworks(List<NetworkResponse> networks) {
this.networks = networks;
}
}

View File

@ -0,0 +1,87 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.api.response;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.EntityReference;
import com.cloud.network.Network;
import com.cloud.serializer.Param;
@EntityReference(value = Network.class)
@SuppressWarnings("unused")
public class NetworkPermissionsResponse extends BaseResponse {
@SerializedName(ApiConstants.NETWORK_ID)
@Param(description = "the network ID")
private String networkId;
@SerializedName(ApiConstants.DOMAIN_ID)
@Param(description = "the ID of the domain to which the network belongs")
private String domainId;
@SerializedName(ApiConstants.DOMAIN)
@Param(description = "the name of the domain to which the network belongs")
private String domainName;
@SerializedName(ApiConstants.ACCOUNT)
@Param(description = "the account the network is available for")
private String accountName;
@SerializedName(ApiConstants.ACCOUNT_ID)
@Param(description = "the ID of account the network is available for")
private String accountId;
@SerializedName(ApiConstants.PROJECT)
@Param(description = "the project the network is available for")
private String projectName;
@SerializedName(ApiConstants.PROJECT_ID)
@Param(description = "the ID of project the network is available for")
private String projectId;
public void setNetworkId(String networkId) {
this.networkId = networkId;
}
public void setDomainId(String domainId) {
this.domainId = domainId;
}
public void setDomainName(String domainName) {
this.domainName = domainName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public void setAccountId(String accountId) {
this.accountId = accountId;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
public void setProjectId(String projectId) {
this.projectId = projectId;
}
}

View File

@ -23,7 +23,7 @@ import java.util.Set;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponseWithAnnotations;
import org.apache.cloudstack.api.BaseResponseWithAssociatedNetwork;
import org.apache.cloudstack.api.EntityReference;
import com.cloud.network.Network;
@ -33,7 +33,7 @@ import com.google.gson.annotations.SerializedName;
@SuppressWarnings("unused")
@EntityReference(value = {Network.class, ProjectAccount.class})
public class NetworkResponse extends BaseResponseWithAnnotations implements ControlledEntityResponse, SetResourceIconResponse {
public class NetworkResponse extends BaseResponseWithAssociatedNetwork implements ControlledEntityResponse, SetResourceIconResponse {
@SerializedName(ApiConstants.ID)
@Param(description = "the id of the network")
@ -195,6 +195,14 @@ public class NetworkResponse extends BaseResponseWithAnnotations implements Cont
@Param(description = "Name of the VPC to which this network belongs", since = "4.15")
private String vpcName;
@SerializedName(ApiConstants.ASSOCIATED_NETWORK_ID)
@Param(description = "the ID of the Network associated with this network")
private String associatedNetworkId;
@SerializedName(ApiConstants.ASSOCIATED_NETWORK)
@Param(description = "the name of the Network associated with this network")
private String associatedNetworkName;
@SerializedName(ApiConstants.CAN_USE_FOR_DEPLOY)
@Param(description = "list networks available for vm deployment")
private Boolean canUseForDeploy;
@ -512,6 +520,14 @@ public class NetworkResponse extends BaseResponseWithAnnotations implements Cont
this.vpcName = vpcName;
}
public void setAssociatedNetworkId(String associatedNetworkId) {
this.associatedNetworkId = associatedNetworkId;
}
public void setAssociatedNetworkName(String associatedNetworkName) {
this.associatedNetworkName = associatedNetworkName;
}
@Override
public void setResourceIconResponse(ResourceIconResponse icon) {
this.icon = icon;

View File

@ -19,7 +19,7 @@ package org.apache.cloudstack.api.response;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.BaseResponseWithAssociatedNetwork;
import org.apache.cloudstack.api.EntityReference;
import com.cloud.network.vpc.VpcGateway;
@ -27,7 +27,7 @@ import com.cloud.serializer.Param;
@EntityReference(value = VpcGateway.class)
@SuppressWarnings("unused")
public class PrivateGatewayResponse extends BaseResponse implements ControlledEntityResponse {
public class PrivateGatewayResponse extends BaseResponseWithAssociatedNetwork implements ControlledEntityResponse {
@SerializedName(ApiConstants.ID)
@Param(description = "the id of the private gateway")
@ -190,5 +190,4 @@ public class PrivateGatewayResponse extends BaseResponse implements ControlledEn
public void setAclName(String aclName) {
this.aclName = aclName;
}
}

View File

@ -177,6 +177,8 @@ public interface NetworkOrchestrationService {
*/
void rollbackNicForMigration(VirtualMachineProfile src, VirtualMachineProfile dst);
boolean isSharedNetworkWithoutSpecifyVlan(NetworkOffering offering);
boolean shutdownNetwork(long networkId, ReservationContext context, boolean cleanupElements);
boolean destroyNetwork(long networkId, ReservationContext context, boolean forced);

View File

@ -53,6 +53,7 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.framework.messagebus.MessageBus;
import org.apache.cloudstack.framework.messagebus.PublishScope;
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.cloudstack.network.dao.NetworkPermissionDao;
import org.apache.commons.lang.BooleanUtils;
import org.apache.log4j.Logger;
@ -318,6 +319,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
ResourceManager resourceManager;
@Inject
private AnnotationDao annotationDao;
@Inject
NetworkPermissionDao networkPermissionDao;
List<NetworkGuru> networkGurus;
@ -2530,7 +2533,9 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
final boolean vlanSpecified = vlanId != null;
if (vlanSpecified != ntwkOff.isSpecifyVlan()) {
if (vlanSpecified) {
throw new InvalidParameterValueException("Can't specify vlan; corresponding offering says specifyVlan=false");
if (!isSharedNetworkWithoutSpecifyVlan(ntwkOff) && !isPrivateGatewayWithoutSpecifyVlan(ntwkOff)) {
throw new InvalidParameterValueException("Can't specify vlan; corresponding offering says specifyVlan=false");
}
} else {
throw new InvalidParameterValueException("Vlan has to be specified; corresponding offering says specifyVlan=true");
}
@ -2540,8 +2545,12 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
URI uri = encodeVlanIdIntoBroadcastUri(vlanId, pNtwk);
// Aux: generate secondary URI for secondary VLAN ID (if provided) for performing checks
URI secondaryUri = StringUtils.isNotBlank(isolatedPvlan) ? BroadcastDomainType.fromString(isolatedPvlan) : null;
if (isSharedNetworkWithoutSpecifyVlan(ntwkOff) || isPrivateGatewayWithoutSpecifyVlan(ntwkOff)) {
bypassVlanOverlapCheck = true;
}
//don't allow to specify vlan tag used by physical network for dynamic vlan allocation
if (!(bypassVlanOverlapCheck && ntwkOff.getGuestType() == GuestType.Shared) && _dcDao.findVnet(zoneId, pNtwk.getId(), BroadcastDomainType.getValue(uri)).size() > 0) {
if (!(bypassVlanOverlapCheck && (ntwkOff.getGuestType() == GuestType.Shared || isPrivateNetwork))
&& _dcDao.findVnet(zoneId, pNtwk.getId(), BroadcastDomainType.getValue(uri)).size() > 0) {
throw new InvalidParameterValueException("The VLAN tag to use for new guest network, " + vlanId + " is already being used for dynamic vlan allocation for the guest network in zone "
+ zone.getName());
}
@ -2764,6 +2773,18 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
return network;
}
@Override
public boolean isSharedNetworkWithoutSpecifyVlan(NetworkOffering offering) {
if (offering == null || offering.getTrafficType() != TrafficType.Guest || offering.getGuestType() != GuestType.Shared) {
return false;
}
return !offering.isSpecifyVlan();
}
private boolean isPrivateGatewayWithoutSpecifyVlan(NetworkOffering ntwkOff) {
return ntwkOff.getId() == _networkOfferingDao.findByUniqueName(NetworkOffering.SystemPrivateGatewayNetworkOfferingWithoutVlan).getId();
}
/**
* Encodes VLAN/VXLAN ID into a Broadcast URI according to the isolation method from the Physical Network.
*
@ -3096,7 +3117,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
throw new CloudRuntimeException("Failed to trash network.");
}
if (!deleteVlansInNetwork(networkFinal.getId(), context.getCaller().getId(), callerAccount)) {
if (!deleteVlansInNetwork(networkFinal, context.getCaller().getId(), callerAccount)) {
s_logger.warn("Failed to delete network " + networkFinal + "; was unable to cleanup corresponding ip ranges");
throw new CloudRuntimeException("Failed to delete network " + networkFinal + "; was unable to cleanup corresponding ip ranges");
} else {
@ -3118,6 +3139,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
}
networkDetailsDao.removeDetails(networkFinal.getId());
networkPermissionDao.removeAllPermissions(networkFinal.getId());
}
final NetworkOffering ntwkOff = _entityMgr.findById(NetworkOffering.class, networkFinal.getNetworkOfferingId());
@ -3150,8 +3172,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
return updateResourceCount;
}
protected boolean deleteVlansInNetwork(final long networkId, final long userId, final Account callerAccount) {
protected boolean deleteVlansInNetwork(final NetworkVO network, final long userId, final Account callerAccount) {
final long networkId = network.getId();
//cleanup Public vlans
final List<VlanVO> publicVlans = _vlanDao.listVlansByNetworkId(networkId);
boolean result = true;
@ -3171,6 +3193,13 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
_privateIpDao.deleteByNetworkId(networkId);
s_logger.debug("Deleted ip range for private network id=" + networkId);
}
// release vlans of user-shared networks without specifyvlan
if (isSharedNetworkWithoutSpecifyVlan(_networkOfferingDao.findById(network.getNetworkOfferingId()))) {
s_logger.debug("Releasing vnet for the network id=" + network.getId());
_dcDao.releaseVnet(BroadcastDomainType.getValue(network.getBroadcastUri()), network.getDataCenterId(),
network.getPhysicalNetworkId(), network.getAccountId(), network.getReservationId());
}
return result;
}
@ -3206,6 +3235,11 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
continue;
}
if (!networkDetailsDao.findDetails(Network.AssociatedNetworkId, String.valueOf(networkId), null).isEmpty()) {
s_logger.debug(String.format("Network %s is associated to a shared network, skipping", networkId));
continue;
}
final Long time = _lastNetworkIdsToFree.remove(networkId);
if (time == null) {
if (s_logger.isDebugEnabled()) {

View File

@ -27,11 +27,11 @@ import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.apache.cloudstack.api.InternalIdentity;
import com.cloud.network.GuestVlan;
@Entity
@Table(name = "op_dc_vnet_alloc")
public class DataCenterVnetVO implements InternalIdentity {
public class DataCenterVnetVO implements GuestVlan {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@ -84,6 +84,7 @@ public class DataCenterVnetVO implements InternalIdentity {
return vnet;
}
@Override
public String getReservationId() {
return reservationId;
}
@ -92,6 +93,7 @@ public class DataCenterVnetVO implements InternalIdentity {
this.reservationId = reservationId;
}
@Override
public Long getAccountId() {
return accountId;
}
@ -100,10 +102,12 @@ public class DataCenterVnetVO implements InternalIdentity {
this.accountId = accountId;
}
@Override
public long getDataCenterId() {
return dataCenterId;
}
@Override
public long getPhysicalNetworkId() {
return physicalNetworkId;
}
@ -112,6 +116,7 @@ public class DataCenterVnetVO implements InternalIdentity {
this.accountGuestVlanMapId = accountGuestVlanMapId;
}
@Override
public Long getAccountGuestVlanMapId() {
return accountGuestVlanMapId;
}

View File

@ -205,8 +205,8 @@ public class VlanVO implements Vlan {
.append("|")
.append(ipRange)
.append("|")
.append("|")
.append(ip6Range)
.append("|")
.append(networkId)
.append("]")
.toString();

View File

@ -25,11 +25,11 @@ import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import com.cloud.network.GuestVlan;
import com.cloud.network.GuestVlanRange;
@Entity
@Table(name = "account_vnet_map")
public class AccountGuestVlanMapVO implements GuestVlan {
public class AccountGuestVlanMapVO implements GuestVlanRange {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)

View File

@ -402,12 +402,12 @@ public class NetworkOfferingVO implements NetworkOffering {
this.state = State.Enabled;
}
public NetworkOfferingVO(String name, Network.GuestType guestType) {
public NetworkOfferingVO(String name, Network.GuestType guestType, boolean specifyVlan) {
this(name,
"System Offering for " + name,
TrafficType.Guest,
true,
true,
specifyVlan,
0,
0,
true,

View File

@ -23,6 +23,7 @@ import javax.annotation.PostConstruct;
import javax.inject.Inject;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import com.cloud.host.HostVO;
@ -376,7 +377,7 @@ public class DomainRouterDaoImpl extends GenericDaoBase<DomainRouterVO, Long> im
public void addRouterToGuestNetwork(final VirtualRouter router, final Network guestNetwork) {
if (_routerNetworkDao.findByRouterAndNetwork(router.getId(), guestNetwork.getId()) == null) {
final NetworkOffering off = _offDao.findById(guestNetwork.getNetworkOfferingId());
if (!off.getName().equalsIgnoreCase(NetworkOffering.SystemPrivateGatewayNetworkOffering)) {
if (!StringUtils.equalsAnyIgnoreCase(NetworkOffering.SystemPrivateGatewayNetworkOffering, NetworkOffering.SystemPrivateGatewayNetworkOfferingWithoutVlan)) {
final TransactionLegacy txn = TransactionLegacy.currentTxn();
txn.start();
//1) add router to network

View File

@ -0,0 +1,61 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.network;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import com.cloud.network.NetworkPermission;
@Entity
@Table(name = "network_permissions")
public class NetworkPermissionVO implements NetworkPermission {
@Id
@Column(name = "id")
private Long id;
@Column(name = "network_id")
private long networkId;
@Column(name = "account_id")
private long accountId;
public NetworkPermissionVO() {
}
public NetworkPermissionVO(long networkId, long accountId) {
this.networkId = networkId;
this.accountId = accountId;
}
@Override
public long getId() {
return id;
}
@Override
public long getNetworkId() {
return networkId;
}
@Override
public long getAccountId() {
return accountId;
}
}

View File

@ -0,0 +1,65 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.network.dao;
import java.util.List;
import com.cloud.utils.db.GenericDao;
import org.apache.cloudstack.network.NetworkPermissionVO;
public interface NetworkPermissionDao extends GenericDao<NetworkPermissionVO, Long> {
/**
* remove the ability to Network vms from the given network for the given
* account names which are valid in the given domain
*
* @param networkId
* id of the network to modify Network permissions
* @param accountIds
* list of account ids
*/
void removePermissions(long networkId, List<Long> accountIds);
/**
* remove all Network permissions associated with a network
*
* @param networkId
*/
void removeAllPermissions(long networkId);
/**
* Find a Network permission by networkId, accountName, and domainId
*
* @param networkId
* the id of the network to search for
* @param accountId
* the id of the account for which permission is being searched
* @return Network permission if found, null otherwise
*/
NetworkPermissionVO findByNetworkAndAccount(long networkId, long accountId);
/**
* List all Network permissions for the given network
*
* @param networkId
* id of the network for which Network permissions will be
* queried
* @return list of Network permissions
*/
List<NetworkPermissionVO> findByNetwork(long networkId);
List<Long> listPermittedNetworkIdsByAccounts(List<Long> permittedAccounts);
}

View File

@ -0,0 +1,98 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.network.dao;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import org.apache.cloudstack.network.NetworkPermissionVO;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
@Component
public class NetworkPermissionDaoImpl extends GenericDaoBase<NetworkPermissionVO, Long> implements NetworkPermissionDao {
private static final Logger s_logger = Logger.getLogger(NetworkPermissionDaoImpl.class);
private SearchBuilder<NetworkPermissionVO> NetworkAndAccountSearch;
private SearchBuilder<NetworkPermissionVO> NetworkIdSearch;
private GenericSearchBuilder<NetworkPermissionVO, Long> FindNetworkIdsByAccount;
protected NetworkPermissionDaoImpl() {
NetworkAndAccountSearch = createSearchBuilder();
NetworkAndAccountSearch.and("networkId", NetworkAndAccountSearch.entity().getNetworkId(), SearchCriteria.Op.EQ);
NetworkAndAccountSearch.and("accountId", NetworkAndAccountSearch.entity().getAccountId(), SearchCriteria.Op.IN);
NetworkAndAccountSearch.done();
NetworkIdSearch = createSearchBuilder();
NetworkIdSearch.and("networkId", NetworkIdSearch.entity().getNetworkId(), SearchCriteria.Op.EQ);
NetworkIdSearch.done();
FindNetworkIdsByAccount = createSearchBuilder(Long.class);
FindNetworkIdsByAccount.select(null, SearchCriteria.Func.DISTINCT, FindNetworkIdsByAccount.entity().getNetworkId());
FindNetworkIdsByAccount.and("account", FindNetworkIdsByAccount.entity().getAccountId(), SearchCriteria.Op.IN);
FindNetworkIdsByAccount.done();
}
@Override
public void removePermissions(long networkId, List<Long> accountIds) {
if (accountIds.isEmpty()) {
return;
}
SearchCriteria<NetworkPermissionVO> sc = NetworkAndAccountSearch.create();
sc.setParameters("networkId", networkId);
sc.setParameters("accountId", accountIds.toArray());
expunge(sc);
}
@Override
public void removeAllPermissions(long networkId) {
SearchCriteria<NetworkPermissionVO> sc = NetworkIdSearch.create();
sc.setParameters("networkId", networkId);
expunge(sc);
}
@Override
public NetworkPermissionVO findByNetworkAndAccount(long networkId, long accountId) {
SearchCriteria<NetworkPermissionVO> sc = NetworkAndAccountSearch.create();
sc.setParameters("networkId", networkId);
sc.setParameters("accountId", accountId);
return findOneBy(sc);
}
@Override
public List<NetworkPermissionVO> findByNetwork(long networkId) {
SearchCriteria<NetworkPermissionVO> sc = NetworkIdSearch.create();
sc.setParameters("networkId", networkId);
return listBy(sc);
}
@Override
public List<Long> listPermittedNetworkIdsByAccounts(List<Long> permittedAccounts) {
SearchCriteria<Long> sc = FindNetworkIdsByAccount.create();
if (permittedAccounts != null && !permittedAccounts.isEmpty()) {
sc.setParameters("account", permittedAccounts.toArray());
return customSearch(sc, null);
}
return new ArrayList<Long>();
}
}

View File

@ -296,4 +296,5 @@
<bean id="VsphereStoragePolicyDaoImpl" class="com.cloud.dc.dao.VsphereStoragePolicyDaoImpl" />
<bean id="TemplateDeployAsIsDetailsDaoImpl" class="com.cloud.deployasis.dao.TemplateDeployAsIsDetailsDaoImpl" />
<bean id="UserVmDeployAsIsDetailsDaoImpl" class="com.cloud.deployasis.dao.UserVmDeployAsIsDetailsDaoImpl" />
<bean id="NetworkPermissionDaoImpl" class="org.apache.cloudstack.network.dao.NetworkPermissionDaoImpl" />
</beans>

View File

@ -645,6 +645,15 @@ CREATE VIEW `cloud`.`domain_router_view` AS
INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) SELECT UUID(), 3, 'listConfigurations', 'ALLOW', (SELECT MAX(`sort_order`)+1 FROM `cloud`.`role_permissions`) ON DUPLICATE KEY UPDATE rule=rule;
INSERT INTO `cloud`.`role_permissions` (`uuid`, `role_id`, `rule`, `permission`, `sort_order`) SELECT UUID(), 3, 'updateConfiguration', 'ALLOW', (SELECT MAX(`sort_order`)+1 FROM `cloud`.`role_permissions`) ON DUPLICATE KEY UPDATE rule=rule;
-- table for network permissions
CREATE TABLE `cloud`.`network_permissions` (
`id` bigint unsigned NOT NULL auto_increment,
`network_id` bigint unsigned NOT NULL,
`account_id` bigint unsigned NOT NULL,
PRIMARY KEY (`id`),
INDEX `i_network_permission_network_id`(`network_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `cloud`.`user_vm_details`(`vm_id`, `name`, `value`)
SELECT `user_vm_details`.`vm_id`, 'SSH.KeyPairNames', `ssh_keypairs`.`keypair_name`
FROM `cloud`.`user_vm_details`

View File

@ -41,6 +41,7 @@ import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.UnavailableCommandException;
import com.cloud.network.Network;
import com.cloud.network.NetworkModel;
import com.cloud.network.router.VirtualRouter;
import com.cloud.network.vpc.VpcOffering;
import com.cloud.network.vpc.dao.VpcOfferingDetailsDao;
import com.cloud.offering.DiskOffering;
@ -173,6 +174,10 @@ public class DomainChecker extends AdapterBase implements SecurityChecker {
return true;
} else if (entity instanceof Network && accessType != null && accessType == AccessType.UseEntry) {
_networkMgr.checkNetworkPermissions(caller, (Network)entity);
} else if (entity instanceof Network && accessType != null && accessType == AccessType.OperateEntry) {
_networkMgr.checkNetworkOperatePermissions(caller, (Network)entity);
} else if (entity instanceof VirtualRouter) {
_networkMgr.checkRouterPermissions(caller, (VirtualRouter)entity);
} else if (entity instanceof AffinityGroup) {
return false;
} else {

View File

@ -46,6 +46,7 @@ import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.api.ApiConstants.DomainDetails;
import org.apache.cloudstack.api.ApiConstants.HostDetails;
import org.apache.cloudstack.api.ApiConstants.VMDetails;
import org.apache.cloudstack.api.BaseResponseWithAssociatedNetwork;
import org.apache.cloudstack.api.ResponseGenerator;
import org.apache.cloudstack.api.ResponseObject.ResponseView;
import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd;
@ -82,6 +83,7 @@ import org.apache.cloudstack.api.response.GlobalLoadBalancerResponse;
import org.apache.cloudstack.api.response.GuestOSResponse;
import org.apache.cloudstack.api.response.GuestOsMappingResponse;
import org.apache.cloudstack.api.response.GuestVlanRangeResponse;
import org.apache.cloudstack.api.response.GuestVlanResponse;
import org.apache.cloudstack.api.response.HostForMigrationResponse;
import org.apache.cloudstack.api.response.HostResponse;
import org.apache.cloudstack.api.response.HypervisorCapabilitiesResponse;
@ -102,6 +104,7 @@ import org.apache.cloudstack.api.response.ManagementServerResponse;
import org.apache.cloudstack.api.response.NetworkACLItemResponse;
import org.apache.cloudstack.api.response.NetworkACLResponse;
import org.apache.cloudstack.api.response.NetworkOfferingResponse;
import org.apache.cloudstack.api.response.NetworkPermissionsResponse;
import org.apache.cloudstack.api.response.NetworkResponse;
import org.apache.cloudstack.api.response.NicExtraDhcpOptionResponse;
import org.apache.cloudstack.api.response.NicResponse;
@ -245,12 +248,14 @@ import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.hypervisor.HypervisorCapabilities;
import com.cloud.network.GuestVlan;
import com.cloud.network.GuestVlanRange;
import com.cloud.network.IpAddress;
import com.cloud.network.Network;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.NetworkModel;
import com.cloud.network.NetworkPermission;
import com.cloud.network.NetworkProfile;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.IsolationType;
@ -277,6 +282,7 @@ import com.cloud.network.as.Counter;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.IPAddressVO;
import com.cloud.network.dao.LoadBalancerVO;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkDetailVO;
import com.cloud.network.dao.NetworkDetailsDao;
import com.cloud.network.dao.NetworkVO;
@ -423,6 +429,8 @@ public class ApiResponseHelper implements ResponseGenerator {
private AnnotationDao annotationDao;
@Inject
private UserStatisticsDao userStatsDao;
@Inject
private NetworkDao networkDao;
@Override
public UserResponse createUserResponse(User user) {
@ -2437,6 +2445,9 @@ public class ApiResponseHelper implements ResponseGenerator {
response.setVpcName(vpc.getName());
}
}
setResponseAssociatedNetworkInformation(response, network.getId());
response.setCanUseForDeploy(ApiDBUtils.canUseForDeploy(network));
// set tag information
@ -2491,6 +2502,18 @@ public class ApiResponseHelper implements ResponseGenerator {
return response;
}
private void setResponseAssociatedNetworkInformation(BaseResponseWithAssociatedNetwork response, Long networkId) {
final NetworkDetailVO detail = networkDetailsDao.findDetail(networkId, Network.AssociatedNetworkId);
if (detail != null) {
Long associatedNetworkId = Long.valueOf(detail.getValue());
NetworkVO associatedNetwork = ApiDBUtils.findNetworkById(associatedNetworkId);
if (associatedNetwork != null) {
response.setAssociatedNetworkId(associatedNetwork.getUuid());
response.setAssociatedNetworkName(associatedNetwork.getName());
}
}
}
@Override
public Long getSecurityGroupId(String groupName, long accountId) {
SecurityGroup sg = ApiDBUtils.getSecurityGroup(groupName, accountId);
@ -2762,7 +2785,7 @@ public class ApiResponseHelper implements ResponseGenerator {
}
@Override
public GuestVlanRangeResponse createDedicatedGuestVlanRangeResponse(GuestVlan vlan) {
public GuestVlanRangeResponse createDedicatedGuestVlanRangeResponse(GuestVlanRange vlan) {
GuestVlanRangeResponse guestVlanRangeResponse = new GuestVlanRangeResponse();
guestVlanRangeResponse.setId(vlan.getUuid());
@ -3202,6 +3225,8 @@ public class ApiResponseHelper implements ResponseGenerator {
response.setAclName(acl.getName());
}
setResponseAssociatedNetworkInformation(response, result.getNetworkId());
response.setObjectName("privategateway");
return response;
@ -4558,6 +4583,95 @@ public class ApiResponseHelper implements ResponseGenerator {
return ApiDBUtils.newResourceIconResponse(resourceIcon);
}
@Override
public GuestVlanResponse createGuestVlanResponse(GuestVlan guestVlan) {
GuestVlanResponse guestVlanResponse = new GuestVlanResponse();
Account owner = null;
if (guestVlan.getAccountId() != null) {
owner = ApiDBUtils.findAccountById(guestVlan.getAccountId());
} else if (guestVlan.getAccountGuestVlanMapId() != null) {
Long accountId = ApiDBUtils.getAccountIdForGuestVlan(guestVlan.getAccountGuestVlanMapId());
owner = ApiDBUtils.findAccountById(accountId);
}
if (owner != null) {
populateAccount(guestVlanResponse, owner.getId());
populateDomain(guestVlanResponse, owner.getDomainId());
}
guestVlanResponse.setId(guestVlan.getId());
guestVlanResponse.setGuestVlan(guestVlan.getVnet());
DataCenterVO zone = ApiDBUtils.findZoneById(guestVlan.getDataCenterId());
if (zone != null) {
guestVlanResponse.setZoneId(zone.getUuid());
guestVlanResponse.setZoneName(zone.getName());
}
PhysicalNetworkVO pnw = ApiDBUtils.findPhysicalNetworkById(guestVlan.getPhysicalNetworkId());
if (pnw != null) {
guestVlanResponse.setPhysicalNetworkId(pnw.getUuid());
guestVlanResponse.setPhysicalNetworkName(pnw.getName());
}
if (guestVlan.getAccountGuestVlanMapId() != null) {
guestVlanResponse.setDedicated(true);
} else {
guestVlanResponse.setDedicated(false);
}
if (guestVlan.getTakenAt() != null) {
guestVlanResponse.setAllocationState("Allocated");
guestVlanResponse.setTaken(guestVlan.getTakenAt());
} else {
guestVlanResponse.setAllocationState("Free");
}
List<NetworkVO> networks = networkDao.listByZoneAndUriAndGuestType(guestVlan.getDataCenterId(), guestVlan.getVnet(), null);
List<NetworkResponse> networkResponses = new ArrayList<NetworkResponse>();
for (Network network : networks) {
NetworkResponse ntwkRsp = createNetworkResponse(ResponseView.Full, network);
networkResponses.add(ntwkRsp);
}
guestVlanResponse.setNetworks(networkResponses);
return guestVlanResponse;
}
@Override
public NetworkPermissionsResponse createNetworkPermissionsResponse(NetworkPermission permission) {
Long networkOwnerDomain = null;
Network network = ApiDBUtils.findNetworkById(permission.getNetworkId());
NetworkPermissionsResponse response = new NetworkPermissionsResponse();
response.setNetworkId(network.getUuid());
Account networkOwner = ApiDBUtils.findAccountById(network.getAccountId());
if (networkOwner != null) {
networkOwnerDomain = networkOwner.getDomainId();
if (networkOwnerDomain != null) {
Domain domain = ApiDBUtils.findDomainById(networkOwnerDomain);
if (domain != null) {
response.setDomainId(domain.getUuid());
response.setDomainName(domain.getName());
}
}
}
Account account = ApiDBUtils.findAccountById(permission.getAccountId());
response.setAccountName(account.getName());
response.setAccountId(account.getUuid());
if (account.getType() == Account.Type.PROJECT) {
// convert account to projectIds
Project project = ApiDBUtils.findProjectByProjectAccountId(account.getId());
if (project.getUuid() != null && !project.getUuid().isEmpty()) {
response.setProjectId(project.getUuid());
} else {
response.setProjectId(String.valueOf(project.getId()));
}
response.setProjectName(project.getName());
}
response.setObjectName("networkpermission");
return response;
}
protected void handleCertificateResponse(String certStr, DirectDownloadCertificateResponse response) {
try {
Certificate cert = CertificateHelper.buildCertificate(certStr);

View File

@ -38,7 +38,9 @@ import org.apache.cloudstack.acl.SecurityChecker;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.api.ACL;
import org.apache.cloudstack.api.ApiArgValidator;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.BaseAsyncCreateCmd;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.BaseCmd.CommandType;
@ -291,7 +293,14 @@ public class ParamProcessWorker implements DispatchWorker {
if (entityOwners != null) {
owners = entityOwners.stream().map(id -> _accountMgr.getAccount(id)).toArray(Account[]::new);
} else {
owners = new Account[]{_accountMgr.getAccount(cmd.getEntityOwnerId())};
if (cmd.getEntityOwnerId() == Account.ACCOUNT_ID_SYSTEM && cmd instanceof BaseAsyncCmd && ((BaseAsyncCmd)cmd).getInstanceType() == ApiCommandJobType.Network) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Skipping access check on the network owner if the owner is ROOT/system.");
}
owners = new Account[]{};
} else {
owners = new Account[]{_accountMgr.getAccount(cmd.getEntityOwnerId())};
}
}
if (cmd instanceof BaseAsyncCreateCmd) {

View File

@ -116,6 +116,7 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
@ -4494,6 +4495,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
}
}
boolean isSharedNetworkWithoutSpecifyVlan = _networkMgr.isSharedNetworkWithoutSpecifyVlan(_networkOfferingDao.findById(network.getNetworkOfferingId()));
if (ipv4) {
final String newCidr = NetUtils.getCidrFromGatewayAndNetmask(vlanGateway, vlanNetmask);
@ -4518,69 +4520,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
checkConflictsWithPortableIpRange(zoneId, vlanId, vlanGateway, vlanNetmask, startIP, endIP);
// Throw an exception if this subnet overlaps with subnet on other VLAN,
// if this is ip range extension, gateway, network mask should be same and ip range should not overlap
final List<VlanVO> vlans = _vlanDao.listByZone(zone.getId());
for (final VlanVO vlan : vlans) {
final String otherVlanGateway = vlan.getVlanGateway();
final String otherVlanNetmask = vlan.getVlanNetmask();
// Continue if it's not IPv4
if ( otherVlanGateway == null || otherVlanNetmask == null ) {
continue;
}
if ( vlan.getNetworkId() == null ) {
continue;
}
final String otherCidr = NetUtils.getCidrFromGatewayAndNetmask(otherVlanGateway, otherVlanNetmask);
if( !NetUtils.isNetworksOverlap(newCidr, otherCidr)) {
continue;
}
// from here, subnet overlaps
if (vlanId.toLowerCase().contains(Vlan.UNTAGGED) || UriUtils.checkVlanUriOverlap(
BroadcastDomainType.getValue(BroadcastDomainType.fromString(vlanId)),
BroadcastDomainType.getValue(BroadcastDomainType.fromString(vlan.getVlanTag())))) {
// For untagged VLAN Id and overlapping URIs we need to expand and verify IP ranges
final String[] otherVlanIpRange = vlan.getIpRange().split("\\-");
final String otherVlanStartIP = otherVlanIpRange[0];
String otherVlanEndIP = null;
if (otherVlanIpRange.length > 1) {
otherVlanEndIP = otherVlanIpRange[1];
}
// extend IP range
if (!vlanGateway.equals(otherVlanGateway) || !vlanNetmask.equals(vlan.getVlanNetmask())) {
throw new InvalidParameterValueException("The IP range has already been added with gateway "
+ otherVlanGateway + " ,and netmask " + otherVlanNetmask
+ ", Please specify the gateway/netmask if you want to extend ip range" );
}
if (!NetUtils.is31PrefixCidr(newCidr)) {
if (NetUtils.ipRangesOverlap(startIP, endIP, otherVlanStartIP, otherVlanEndIP)) {
throw new InvalidParameterValueException("The IP range already has IPs that overlap with the new range." +
" Please specify a different start IP/end IP.");
}
}
} else {
// For tagged or non-overlapping URIs we need to ensure there is no Public traffic type
boolean overlapped = false;
if (network.getTrafficType() == TrafficType.Public) {
overlapped = true;
} else {
final Long nwId = vlan.getNetworkId();
if (nwId != null) {
final Network nw = _networkModel.getNetwork(nwId);
if (nw != null && nw.getTrafficType() == TrafficType.Public) {
overlapped = true;
}
}
}
if (overlapped) {
throw new InvalidParameterValueException("The IP range with tag: " + vlan.getVlanTag()
+ " in zone " + zone.getName()
+ " has overlapped with the subnet. Please specify a different gateway/netmask.");
}
}
if (!isSharedNetworkWithoutSpecifyVlan) {
checkZoneVlanIpOverlap(zone, network, newCidr, vlanId, vlanGateway, vlanNetmask, startIP, endIP);
}
}
@ -4611,6 +4552,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
}
// Check if the vlan is being used
if (isSharedNetworkWithoutSpecifyVlan) {
bypassVlanOverlapCheck = true;
}
if (!bypassVlanOverlapCheck && _zoneDao.findVnet(zoneId, physicalNetworkId, BroadcastDomainType.getValue(BroadcastDomainType.fromString(vlanId))).size() > 0) {
throw new InvalidParameterValueException("The VLAN tag " + vlanId + " is already being used for dynamic vlan allocation for the guest network in zone "
+ zone.getName());
@ -4632,6 +4576,68 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
return vlan;
}
private void checkZoneVlanIpOverlap(DataCenterVO zone, Network network, String newCidr, String vlanId, String vlanGateway, String vlanNetmask, String startIP, String endIP) {
// Throw an exception if this subnet overlaps with subnet on other VLAN,
// if this is ip range extension, gateway, network mask should be same and ip range should not overlap
final List<VlanVO> vlans = _vlanDao.listByZone(zone.getId());
for (final VlanVO vlan : vlans) {
final String otherVlanGateway = vlan.getVlanGateway();
final String otherVlanNetmask = vlan.getVlanNetmask();
// Continue if it's not IPv4
if (ObjectUtils.anyNull(otherVlanGateway, otherVlanNetmask, vlan.getNetworkId())) {
continue;
}
final String otherCidr = NetUtils.getCidrFromGatewayAndNetmask(otherVlanGateway, otherVlanNetmask);
if( !NetUtils.isNetworksOverlap(newCidr, otherCidr)) {
continue;
}
// from here, subnet overlaps
if (vlanId.toLowerCase().contains(Vlan.UNTAGGED) || UriUtils.checkVlanUriOverlap(
BroadcastDomainType.getValue(BroadcastDomainType.fromString(vlanId)),
BroadcastDomainType.getValue(BroadcastDomainType.fromString(vlan.getVlanTag())))) {
// For untagged VLAN Id and overlapping URIs we need to expand and verify IP ranges
final String[] otherVlanIpRange = vlan.getIpRange().split("\\-");
final String otherVlanStartIP = otherVlanIpRange[0];
String otherVlanEndIP = null;
if (otherVlanIpRange.length > 1) {
otherVlanEndIP = otherVlanIpRange[1];
}
// extend IP range
if (!vlanGateway.equals(otherVlanGateway) || !vlanNetmask.equals(vlan.getVlanNetmask())) {
throw new InvalidParameterValueException("The IP range has already been added with gateway "
+ otherVlanGateway + " ,and netmask " + otherVlanNetmask
+ ", Please specify the gateway/netmask if you want to extend ip range" );
}
if (!NetUtils.is31PrefixCidr(newCidr) && NetUtils.ipRangesOverlap(startIP, endIP, otherVlanStartIP, otherVlanEndIP)) {
throw new InvalidParameterValueException("The IP range already has IPs that overlap with the new range." +
" Please specify a different start IP/end IP.");
}
} else {
// For tagged or non-overlapping URIs we need to ensure there is no Public traffic type
boolean overlapped = false;
if (network.getTrafficType() == TrafficType.Public) {
overlapped = true;
} else {
final Long nwId = vlan.getNetworkId();
if (nwId != null) {
final Network nw = _networkModel.getNetwork(nwId);
if (nw != null && nw.getTrafficType() == TrafficType.Public) {
overlapped = true;
}
}
}
if (overlapped) {
throw new InvalidParameterValueException("The IP range with tag: " + vlan.getVlanTag()
+ " in zone " + zone.getName()
+ " has overlapped with the subnet. Please specify a different gateway/netmask.");
}
}
}
}
private VlanVO commitVlanAndIpRange(final long zoneId, final long networkId, final long physicalNetworkId, final Long podId, final String startIP, final String endIP,
final String vlanGateway, final String vlanNetmask, final String vlanId, final Domain domain, final Account vlanOwner, final String vlanIp6Gateway, final String vlanIp6Cidr,
final boolean ipv4, final DataCenterVO zone, final VlanType vlanType, final String ipv6Range, final String ipRange, final boolean forSystemVms) {
@ -5025,7 +5031,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
@Override
public void doInTransactionWithoutResult(final TransactionStatus status) {
_publicIpAddressDao.deletePublicIPRange(vlanDbId);
s_logger.debug(String.format("Delete Public IP Range (from user_ip_address, where vlan_db_d=%s)", vlanDbId));
s_logger.debug(String.format("Delete Public IP Range (from user_ip_address, where vlan_db_id=%s)", vlanDbId));
_vlanDao.remove(vlanDbId);
s_logger.debug(String.format("Mark vlan as Remove vlan (vlan_db_id=%s)", vlanDbId));
@ -6037,14 +6043,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
final int multicastRate = multicastRateStr == null ? 10 : Integer.parseInt(multicastRateStr);
tags = com.cloud.utils.StringUtils.cleanupTags(tags);
// specifyVlan should always be true for Shared network offerings
if (!specifyVlan && type == GuestType.Shared) {
Set<Provider> connectivityProviders = serviceProviderMap != null ? serviceProviderMap.get(Service.Connectivity) : null;
if (CollectionUtils.isEmpty(connectivityProviders) || !_networkModel.providerSupportsCapability(connectivityProviders, Service.Connectivity, Capability.NoVlan)) {
throw new InvalidParameterValueException("SpecifyVlan should be true if network offering's type is " + type);
}
}
// specifyIpRanges should always be true for Shared networks
// specifyIpRanges can only be true for Isolated networks with no Source
// Nat service

View File

@ -41,6 +41,8 @@ import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.lb.dao.ApplicationLoadBalancerRuleDao;
import org.apache.cloudstack.network.NetworkPermissionVO;
import org.apache.cloudstack.network.dao.NetworkPermissionDao;
import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger;
@ -74,6 +76,8 @@ import com.cloud.network.addr.PublicIp;
import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.IPAddressVO;
import com.cloud.network.dao.NetworkAccountDao;
import com.cloud.network.dao.NetworkAccountVO;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkDomainDao;
import com.cloud.network.dao.NetworkDomainVO;
@ -91,6 +95,7 @@ import com.cloud.network.element.IpDeployer;
import com.cloud.network.element.IpDeployingRequester;
import com.cloud.network.element.NetworkElement;
import com.cloud.network.element.UserDataServiceProvider;
import com.cloud.network.router.VirtualRouter;
import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.network.rules.FirewallRuleVO;
import com.cloud.network.rules.dao.PortForwardingRulesDao;
@ -168,6 +173,8 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel, Confi
VpcGatewayDao _vpcGatewayDao;
@Inject
ProjectDao projectDao;
@Inject
NetworkPermissionDao _networkPermissionDao;
private List<NetworkElement> networkElements;
@ -179,6 +186,8 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel, Confi
this.networkElements = networkElements;
}
@Inject
NetworkAccountDao _networkAccountDao;
@Inject
NetworkDomainDao _networkDomainDao;
@Inject
@ -217,7 +226,6 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel, Confi
private NetworkService _networkService;
private final HashMap<String, NetworkOfferingVO> _systemNetworks = new HashMap<String, NetworkOfferingVO>(5);
static Long s_privateOfferingId = null;
SearchBuilder<IPAddressVO> IpAddressSearch;
SearchBuilder<NicVO> NicForTrafficTypeSearch;
@ -1665,26 +1673,11 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel, Confi
throw new PermissionDeniedException("Unable to use network with id= " + ((NetworkVO)network).getUuid() +
", network does not have an owner");
if (owner.getType() != Account.Type.PROJECT && networkOwner.getType() == Account.Type.PROJECT) {
User user = CallContext.current().getCallingUser();
Project project = projectDao.findByProjectAccountId(network.getAccountId());
if (project == null) {
throw new CloudRuntimeException("Unable to find project to which the network belongs to");
}
ProjectAccount projectAccountUser = _projectAccountDao.findByProjectIdUserId(project.getId(), user.getAccountId(), user.getId());
if (projectAccountUser != null) {
if (!_projectAccountDao.canUserAccessProjectAccount(user.getAccountId(), user.getId(), network.getAccountId())) {
throw new PermissionDeniedException("Unable to use network with id= " + ((NetworkVO)network).getUuid() +
", permission denied");
}
} else {
if (!_projectAccountDao.canAccessProjectAccount(owner.getAccountId(), network.getAccountId())) {
throw new PermissionDeniedException("Unable to use network with id= " + ((NetworkVO) network).getUuid() +
", permission denied");
}
}
checkProjectNetworkPermissions(owner, networkOwner, network);
} else {
List<NetworkVO> networkMap = _networksDao.listBy(owner.getId(), network.getId());
if (networkMap == null || networkMap.isEmpty()) {
NetworkPermissionVO networkPermission = _networkPermissionDao.findByNetworkAndAccount(network.getId(), owner.getId());
if (CollectionUtils.isEmpty(networkMap) && networkPermission == null) {
throw new PermissionDeniedException("Unable to use network with id= " + ((NetworkVO)network).getUuid() +
", permission denied");
}
@ -1702,6 +1695,131 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel, Confi
}
}
private void checkProjectNetworkPermissions(Account owner, Account networkOwner, Network network){
User user = CallContext.current().getCallingUser();
Project project = projectDao.findByProjectAccountId(networkOwner.getId());
if (project == null) {
throw new CloudRuntimeException("Unable to find project to which the network belongs to");
}
ProjectAccount projectAccountUser = _projectAccountDao.findByProjectIdUserId(project.getId(), user.getAccountId(), user.getId());
if (projectAccountUser != null) {
if (!_projectAccountDao.canUserAccessProjectAccount(user.getAccountId(), user.getId(), networkOwner.getId())) {
throw new PermissionDeniedException("Unable to use network with id= " + ((NetworkVO)network).getUuid() +
", permission denied");
}
} else {
if (!_projectAccountDao.canAccessProjectAccount(owner.getAccountId(), networkOwner.getId())) {
throw new PermissionDeniedException("Unable to use network with id= " + ((NetworkVO) network).getUuid() +
", permission denied");
}
}
}
@Override
public void checkNetworkOperatePermissions(Account owner, Network network) {
if (network == null) {
throw new CloudRuntimeException("cannot check permissions on (Network) <null>");
}
if (owner.getType() == Account.Type.ADMIN) {
return;
}
if (network.getGuestType() == GuestType.Shared) {
checkSharedNetworkOperatePermissions(owner, network);
} else {
checkNonSharedNetworkOperatePermissions(owner, network);
}
}
@Override
public void checkRouterPermissions(Account owner, VirtualRouter router) {
Account account = _accountMgr.getAccount(router.getAccountId());
try {
_accountMgr.checkAccess(owner, null, true, account);
return;
} catch (PermissionDeniedException ex) {
s_logger.info("Account " + owner + " do not have permission on router owner " + account);
}
List<NicVO> routerNics = _nicDao.listByVmId(router.getId());
for (final Nic routerNic : routerNics) {
final NetworkVO network = _networksDao.findById(routerNic.getNetworkId());
if (TrafficType.Guest.equals(network.getTrafficType())) {
checkNetworkOperatePermissions(owner, network);
}
}
}
private void checkNonSharedNetworkOperatePermissions(Account owner, Network network) {
// check on isolated/L2 networks
Account networkOwner = _accountDao.findByIdIncludingRemoved(network.getAccountId());
if (owner.getType() == Account.Type.DOMAIN_ADMIN) {
if (!_domainDao.isChildDomain(owner.getDomainId(), networkOwner.getDomainId())) {
throw new PermissionDeniedException(String.format("network %s cannot be operated by domain admin %s", network, owner));
}
} else if (owner.getType() == Account.Type.NORMAL) {
if (owner.getType() != Account.Type.PROJECT && networkOwner.getType() == Account.Type.PROJECT) {
checkProjectNetworkPermissions(owner, networkOwner, network);
} else if (networkOwner.getAccountId() != owner.getAccountId()) {
throw new PermissionDeniedException(String.format("network %s cannot be operated by normal user %s", network, owner));
}
} else {
throw new PermissionDeniedException(String.format("network %s cannot be operated by this account %s", network, owner));
}
}
private void checkSharedNetworkOperatePermissions(Account owner, Network network) {
NetworkOffering networkOffering = _networkOfferingDao.findById(network.getNetworkOfferingId());
if (networkOffering.isSpecifyVlan() && owner.getType() != Account.Type.ADMIN) {
throw new PermissionDeniedException(String.format("Shared network %s with specifyvlan=true can only be operated by root admin", network));
}
if (owner.getType() == Account.Type.DOMAIN_ADMIN) {
if (network.getAclType() == ACLType.Domain) {
// Allow domain admins to operate shared network for their domain.
Long networkDomainId = getDomainIdForSharedNetwork(network);
if (!_domainDao.isChildDomain(owner.getDomainId(), networkDomainId)) {
throw new PermissionDeniedException(String.format("Shared network %s belongs to another domain cannot be operated by domain admin %s", network, owner));
}
} else if (network.getAclType() == ACLType.Account) {
// Allow domain admins to operate shared network for an account in their domain.
Long networkAccountId = getAccountIdForSharedNetwork(network);
if (!_domainDao.isChildDomain(owner.getDomainId(), _accountDao.findByIdIncludingRemoved(networkAccountId).getDomainId())) {
throw new PermissionDeniedException(String.format("Shared network %s belongs to an account in another domain cannot be operated by domain admin %s", network, owner));
}
}
} else if (owner.getType() == Account.Type.NORMAL) {
// Allow normal users to operate shared network for themselves.
if (network.getAclType() == ACLType.Account) {
// Allow domain admin to operate shared network for an account in its domain.
Long networkAccountId = getAccountIdForSharedNetwork(network);
Account networkOwner = _accountDao.findByIdIncludingRemoved(networkAccountId);
if (owner.getType() != Account.Type.PROJECT && networkOwner.getType() == Account.Type.PROJECT) {
checkProjectNetworkPermissions(owner, networkOwner, network);
} else if (networkOwner.getAccountId() != owner.getAccountId()) {
throw new PermissionDeniedException(String.format("Shared network %s belongs to another account cannot be operated by normal user %s", network, owner));
}
} else {
throw new PermissionDeniedException(String.format("Shared network %s belongs to domain cannot be operated by normal user %s", network, owner));
}
} else if (owner.getType() != Account.Type.ADMIN) {
throw new PermissionDeniedException(String.format("Shared network %s cannot be operated by account %s with type = %d", network, owner, owner.getType()));
}
}
private Long getAccountIdForSharedNetwork(Network network) {
NetworkAccountVO networkAccountMap = _networkAccountDao.getAccountNetworkMapByNetworkId(network.getId());
if (networkAccountMap == null) {
throw new CloudRuntimeException(String.format("Cannot find account info for Shared network %s with aclType=Account", network));
}
return networkAccountMap.getAccountId();
}
private Long getDomainIdForSharedNetwork(Network network) {
NetworkDomainVO networkDomainMap = _networkDomainDao.getDomainNetworkMapByNetworkId(network.getId());
if (networkDomainMap == null) {
throw new CloudRuntimeException(String.format("Cannot find domain info for Shared network %s with aclType=Domain", network));
}
return networkDomainMap.getDomainId();
}
@Override
public String getDefaultPublicTrafficLabel(long dcId, HypervisorType hypervisorType) {
try {
@ -2089,10 +2207,12 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel, Confi
NetworkOfferingVO storageNetworkOffering = new NetworkOfferingVO(NetworkOffering.SystemStorageNetwork, TrafficType.Storage, true);
storageNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(storageNetworkOffering);
_systemNetworks.put(NetworkOffering.SystemStorageNetwork, storageNetworkOffering);
NetworkOfferingVO privateGatewayNetworkOffering = new NetworkOfferingVO(NetworkOffering.SystemPrivateGatewayNetworkOffering, GuestType.Isolated);
NetworkOfferingVO privateGatewayNetworkOffering = new NetworkOfferingVO(NetworkOffering.SystemPrivateGatewayNetworkOffering, GuestType.Isolated, true);
privateGatewayNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(privateGatewayNetworkOffering);
_systemNetworks.put(NetworkOffering.SystemPrivateGatewayNetworkOffering, privateGatewayNetworkOffering);
s_privateOfferingId = privateGatewayNetworkOffering.getId();
NetworkOfferingVO privateGatewayNetworkOfferingWithoutVlan = new NetworkOfferingVO(NetworkOffering.SystemPrivateGatewayNetworkOfferingWithoutVlan, GuestType.Isolated, false);
privateGatewayNetworkOfferingWithoutVlan = _networkOfferingDao.persistDefaultNetworkOffering(privateGatewayNetworkOfferingWithoutVlan);
_systemNetworks.put(NetworkOffering.SystemPrivateGatewayNetworkOfferingWithoutVlan, privateGatewayNetworkOfferingWithoutVlan);
IpAddressSearch = _ipAddressDao.createSearchBuilder();
IpAddressSearch.and("accountId", IpAddressSearch.entity().getAllocatedToAccountId(), Op.EQ);

View File

@ -16,6 +16,8 @@
// under the License.
package com.cloud.network;
import org.apache.commons.lang3.EnumUtils;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.URI;
@ -25,6 +27,7 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
@ -35,6 +38,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
@ -46,10 +50,16 @@ import org.apache.cloudstack.api.command.admin.address.ReleasePodIpCmdByAdmin;
import org.apache.cloudstack.api.command.admin.network.CreateNetworkCmdByAdmin;
import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd;
import org.apache.cloudstack.api.command.admin.network.ListDedicatedGuestVlanRangesCmd;
import org.apache.cloudstack.api.command.admin.network.ListGuestVlansCmd;
import org.apache.cloudstack.api.command.admin.network.ListNetworksCmdByAdmin;
import org.apache.cloudstack.api.command.admin.network.UpdateNetworkCmdByAdmin;
import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd;
import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd;
import org.apache.cloudstack.api.command.user.network.CreateNetworkPermissionsCmd;
import org.apache.cloudstack.api.command.user.network.ListNetworkPermissionsCmd;
import org.apache.cloudstack.api.command.user.network.ListNetworksCmd;
import org.apache.cloudstack.api.command.user.network.RemoveNetworkPermissionsCmd;
import org.apache.cloudstack.api.command.user.network.ResetNetworkPermissionsCmd;
import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd;
import org.apache.cloudstack.api.command.user.network.UpdateNetworkCmd;
import org.apache.cloudstack.api.command.user.vm.ListNicsCmd;
@ -61,6 +71,8 @@ import org.apache.cloudstack.framework.config.Configurable;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.framework.messagebus.MessageBus;
import org.apache.cloudstack.framework.messagebus.PublishScope;
import org.apache.cloudstack.network.NetworkPermissionVO;
import org.apache.cloudstack.network.dao.NetworkPermissionDao;
import org.apache.cloudstack.network.element.InternalLoadBalancerElementService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
@ -139,6 +151,7 @@ import com.cloud.network.element.NetworkElement;
import com.cloud.network.element.OvsProviderVO;
import com.cloud.network.element.VirtualRouterElement;
import com.cloud.network.element.VpcVirtualRouterElement;
import com.cloud.network.guru.GuestNetworkGuru;
import com.cloud.network.guru.NetworkGuru;
import com.cloud.network.rules.FirewallRule.Purpose;
import com.cloud.network.rules.FirewallRuleVO;
@ -181,6 +194,7 @@ import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.EntityManager;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.JoinBuilder;
import com.cloud.utils.db.QueryBuilder;
import com.cloud.utils.db.SearchBuilder;
@ -259,6 +273,8 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
@Inject
NetworkDao _networksDao = null;
@Inject
NetworkPermissionDao _networkPermissionDao = null;
@Inject
NicDao _nicDao = null;
@Inject
RulesManager _rulesMgr;
@ -306,7 +322,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
@Inject
InternalLoadBalancerElementService _internalLbElementSvc;
@Inject
DataCenterVnetDao _datacneterVnet;
DataCenterVnetDao _dcVnetDao;
@Inject
AccountGuestVlanMapDao _accountGuestVlanMapDao;
@Inject
@ -1228,6 +1244,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
String isolatedPvlan = cmd.getIsolatedPvlan();
String externalId = cmd.getExternalId();
String isolatedPvlanType = cmd.getIsolatedPvlanType();
Long associatedNetworkId = cmd.getAssociatedNetworkId();
// Validate network offering
NetworkOfferingVO ntwkOff = _networkOfferingDao.findById(networkOfferingId);
@ -1302,15 +1319,16 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
if (ntwkOff.getGuestType() == GuestType.Isolated || ntwkOff.getGuestType() == GuestType.L2) {
aclType = ACLType.Account;
} else if (ntwkOff.getGuestType() == GuestType.Shared) {
aclType = ACLType.Domain;
if (_accountMgr.isRootAdmin(caller.getId())) {
aclType = ACLType.Domain;
} else if (_accountMgr.isNormalUser(caller.getId())) {
aclType = ACLType.Account;
} else {
throw new InvalidParameterValueException("AclType must be specified for shared network created by domain admin");
}
}
}
// Only Admin can create Shared networks
if ((ntwkOff.getGuestType() == GuestType.Shared) && !_accountMgr.isAdmin(caller.getId())) {
throw new InvalidParameterValueException("Only Admins can create network with guest type " + GuestType.Shared);
}
if (ntwkOff.getGuestType() != GuestType.Shared && (!StringUtils.isAllBlank(routerIp, routerIpv6))) {
throw new InvalidParameterValueException("Router IP can be specified only for Shared networks");
}
@ -1451,12 +1469,16 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
validateRouterIps(routerIp, routerIpv6, startIP, endIP, gateway, netmask, startIPv6, endIPv6, ip6Cidr);
if (StringUtils.isNotBlank(isolatedPvlan) && (zone.getNetworkType() != NetworkType.Advanced || ntwkOff.getGuestType() == GuestType.Isolated)) {
throw new InvalidParameterValueException("Can only support create Private VLAN network with advanced shared or L2 network!");
}
if (StringUtils.isNotBlank(isolatedPvlan) && ipv6) {
throw new InvalidParameterValueException("Can only support create Private VLAN network with IPv4!");
if (StringUtils.isNotBlank(isolatedPvlan)) {
if (!_accountMgr.isRootAdmin(caller.getId())) {
throw new InvalidParameterValueException("Only ROOT admin is allowed to create Private VLAN network");
}
if (zone.getNetworkType() != NetworkType.Advanced || ntwkOff.getGuestType() == GuestType.Isolated) {
throw new InvalidParameterValueException("Can only support create Private VLAN network with advanced shared or L2 network!");
}
if (ipv6) {
throw new InvalidParameterValueException("Can only support create Private VLAN network with IPv4!");
}
}
Pair<String, PVlanType> pvlanPair = getPrivateVlanPair(isolatedPvlan, isolatedPvlanType, vlanId);
@ -1473,6 +1495,11 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
validateNetworkOfferingForNonRootAdminUser(ntwkOff);
}
// Ignore vlanId if it is passed but specifyvlan=false in network offering
if (ntwkOff.getGuestType() == GuestType.Shared && ! ntwkOff.isSpecifyVlan() && vlanId != null) {
throw new InvalidParameterValueException("Cannot specify vlanId when create a network from network offering with specifyvlan=false");
}
// Don't allow to specify vlan if the caller is not ROOT admin
if (!_accountMgr.isRootAdmin(caller.getId()) && (ntwkOff.isSpecifyVlan() || vlanId != null || bypassVlanOverlapCheck)) {
throw new InvalidParameterValueException("Only ROOT admin is allowed to specify vlanId or bypass vlan overlap check");
@ -1531,9 +1558,23 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
throwInvalidIdException("Network offering with specified id doesn't support adding multiple ip ranges", ntwkOff.getUuid(), "networkOfferingId");
}
Network associatedNetwork = null;
if (associatedNetworkId != null) {
if (vlanId != null) {
throw new InvalidParameterValueException("Associated network and vlanId are mutually exclusive");
}
if (!_networkMgr.isSharedNetworkWithoutSpecifyVlan(ntwkOff)) {
throw new InvalidParameterValueException("Can only create Shared network with associated network if specifyVlan is false");
}
associatedNetwork = implementAssociatedNetwork(associatedNetworkId, caller, owner, zone,
aclType == ACLType.Domain ? domainId : null,
aclType == ACLType.Account ? owner.getAccountId() : null,
cidr, startIP, endIP);
}
Network network = commitNetwork(networkOfferingId, gateway, startIP, endIP, netmask, networkDomain, vlanId, bypassVlanOverlapCheck, name, displayText, caller, physicalNetworkId, zoneId,
domainId, isDomainSpecific, subdomainAccess, vpcId, startIPv6, endIPv6, ip6Gateway, ip6Cidr, displayNetwork, aclId, secondaryVlanId, privateVlanType, ntwkOff, pNtwk, aclType, owner, cidr, createVlan,
externalId, routerIp, routerIpv6);
externalId, routerIp, routerIpv6, associatedNetwork);
if (hideIpAddressUsage) {
_networkDetailsDao.persist(new NetworkDetailVO(network.getId(), Network.hideIpAddressUsage, String.valueOf(hideIpAddressUsage), false));
@ -1541,27 +1582,72 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
// if the network offering has persistent set to true, implement the network
if (ntwkOff.isPersistent()) {
try {
DeployDestination dest = new DeployDestination(zone, null, null, null);
UserVO callerUser = _userDao.findById(CallContext.current().getCallingUserId());
Journal journal = new Journal.LogJournal("Implementing " + network, s_logger);
ReservationContext context = new ReservationContextImpl(UUID.randomUUID().toString(), journal, callerUser, caller);
s_logger.debug("Implementing network " + network + " as a part of network provision for persistent network");
Pair<? extends NetworkGuru, ? extends Network> implementedNetwork = _networkMgr.implementNetwork(network.getId(), dest, context);
if (implementedNetwork == null || implementedNetwork.first() == null) {
s_logger.warn("Failed to provision the network " + network);
}
network = implementedNetwork.second();
} catch (ResourceUnavailableException ex) {
s_logger.warn("Failed to implement persistent guest network " + network + "due to ", ex);
CloudRuntimeException e = new CloudRuntimeException("Failed to implement persistent guest network");
e.addProxyObject(network.getUuid(), "networkId");
throw e;
}
return implementedNetworkInCreation(caller, zone, network);
}
return network;
}
private Network implementAssociatedNetwork(Long associatedNetworkId, Account caller, Account owner, DataCenter zone, Long domainId, Long accountId,
String cidr, String startIp, String endIp) throws InsufficientCapacityException {
Network associatedNetwork = _networksDao.findById(associatedNetworkId);
if (associatedNetwork == null) {
throw new InvalidParameterValueException("Cannot find associated network with id = " + associatedNetworkId);
}
if (associatedNetwork.getGuestType() != GuestType.Isolated && associatedNetwork.getGuestType() != GuestType.L2) {
throw new InvalidParameterValueException("Associated network MUST be an Isolated or L2 network");
}
_accountMgr.checkAccess(caller, null, true, associatedNetwork);
if (accountId != null && associatedNetwork.getAccountId() != accountId) {
throw new InvalidParameterValueException("The new network and associated network MUST be owned by same account");
}
if (domainId != null && associatedNetwork.getDomainId() != domainId) {
throw new InvalidParameterValueException("The new network and associated network MUST be in same domain");
}
if (cidr != null && associatedNetwork.getCidr() != null && NetUtils.isNetworksOverlap(cidr, associatedNetwork.getCidr())) {
throw new InvalidParameterValueException("The cidr overlaps with associated network: " + associatedNetwork.getName());
}
List<NetworkDetailVO> associatedNetworks = _networkDetailsDao.findDetails(Network.AssociatedNetworkId, String.valueOf(associatedNetworkId), null);
for (NetworkDetailVO networkDetailVO : associatedNetworks) {
NetworkVO associatedNetwork2 = _networksDao.findById(networkDetailVO.getResourceId());
if (associatedNetwork2 != null) {
List<VlanVO> vlans = _vlanDao.listVlansByNetworkId(associatedNetwork2.getId());
if (vlans.isEmpty()) {
continue;
}
String startIP2 = vlans.get(0).getIpRange().split("-")[0];
String endIP2 = vlans.get(0).getIpRange().split("-")[1];
if (StringUtils.isNoneBlank(startIp, startIP2) && NetUtils.ipRangesOverlap(startIp, endIp, startIP2, endIP2)) {
throw new InvalidParameterValueException("The startIp/endIp overlaps with network: " + associatedNetwork2.getName());
}
}
}
associatedNetwork = implementedNetworkInCreation(caller, zone, associatedNetwork);
if (associatedNetwork == null || (associatedNetwork.getState() != Network.State.Implemented && associatedNetwork.getState() != Network.State.Setup)) {
throw new InvalidParameterValueException("Unable to implement associated network " + associatedNetwork);
}
return associatedNetwork;
}
private Network implementedNetworkInCreation(final Account caller, final DataCenter zone, final Network network) throws InsufficientCapacityException {
try {
DeployDestination dest = new DeployDestination(zone, null, null, null);
UserVO callerUser = _userDao.findById(CallContext.current().getCallingUserId());
Journal journal = new Journal.LogJournal("Implementing " + network, s_logger);
ReservationContext context = new ReservationContextImpl(UUID.randomUUID().toString(), journal, callerUser, caller);
s_logger.debug("Implementing network " + network + " as a part of network provision for persistent network");
Pair<? extends NetworkGuru, ? extends Network> implementedNetwork = _networkMgr.implementNetwork(network.getId(), dest, context);
if (implementedNetwork == null || implementedNetwork.first() == null) {
s_logger.warn("Failed to provision the network " + network);
}
return implementedNetwork.second();
} catch (ResourceUnavailableException ex) {
s_logger.warn("Failed to implement persistent guest network " + network + "due to ", ex);
CloudRuntimeException e = new CloudRuntimeException("Failed to implement persistent guest network");
e.addProxyObject(network.getUuid(), "networkId");
throw e;
}
}
private void validateNetworkOfferingForNonRootAdminUser(NetworkOfferingVO ntwkOff) {
if (ntwkOff.getTrafficType() != TrafficType.Guest) {
throw new InvalidParameterValueException("This user can only create a Guest network");
@ -1569,9 +1655,12 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
if (ntwkOff.getGuestType() == GuestType.L2 || ntwkOff.getGuestType() == GuestType.Isolated) {
s_logger.debug(String.format("Creating a network from network offerings having traffic type [%s] and network type [%s].",
TrafficType.Guest, ntwkOff.getGuestType()));
} else if (ntwkOff.getGuestType() == GuestType.Shared && ! ntwkOff.isSpecifyVlan()) {
s_logger.debug(String.format("Creating a network from network offerings having traffic type [%s] and network type [%s] with specifyVlan=%s.",
TrafficType.Guest, GuestType.Shared, ntwkOff.isSpecifyVlan()));
} else {
throw new InvalidParameterValueException(
String.format("This user can only create an %s network or a %s network.", GuestType.Isolated, GuestType.L2));
String.format("This user can only create an %s network, a %s network or a %s network with specifyVlan=false.", GuestType.Isolated, GuestType.L2, GuestType.Shared));
}
}
@ -1618,11 +1707,12 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
}
}
private Network commitNetwork(final Long networkOfferingId, final String gateway, final String startIP, final String endIP, final String netmask, final String networkDomain, final String vlanId,
private Network commitNetwork(final Long networkOfferingId, final String gateway, final String startIP, final String endIP, final String netmask, final String networkDomain, final String vlanIdFinal,
final Boolean bypassVlanOverlapCheck, final String name, final String displayText, final Account caller, final Long physicalNetworkId, final Long zoneId, final Long domainId,
final boolean isDomainSpecific, final Boolean subdomainAccessFinal, final Long vpcId, final String startIPv6, final String endIPv6, final String ip6Gateway, final String ip6Cidr,
final Boolean displayNetwork, final Long aclId, final String isolatedPvlan, final PVlanType isolatedPvlanType, final NetworkOfferingVO ntwkOff, final PhysicalNetwork pNtwk, final ACLType aclType, final Account ownerFinal,
final String cidr, final boolean createVlan, final String externalId, String routerIp, String routerIpv6) throws InsufficientCapacityException, ResourceAllocationException {
final String cidr, final boolean createVlan, final String externalId, String routerIp, String routerIpv6,
final Network associatedNetwork) throws InsufficientCapacityException, ResourceAllocationException {
try {
Network network = Transaction.execute(new TransactionCallbackWithException<Network, Exception>() {
@Override
@ -1645,6 +1735,20 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
owner = _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM);
}
String vlanId = vlanIdFinal;
if (createVlan && vlanId == null && ntwkOff.getGuestType() == Network.GuestType.Shared && ! ntwkOff.isSpecifyVlan()) {
if (associatedNetwork != null) {
// Get vlanId from associated network
vlanId = associatedNetwork.getBroadcastUri().toString();
} else {
// Allocate a vnet to shared network with specifyvlan=false
vlanId = _dcDao.allocateVnet(zoneId, physicalNetworkId, owner.getAccountId(), null, GuestNetworkGuru.UseSystemGuestVlans.valueIn(owner.getAccountId()));
if (vlanId == null) {
throw new InvalidParameterValueException("Cannot allocate a vnet for this Shared network");
}
}
}
// Create guest network
Network network = null;
if (vpcId != null) {
@ -1680,11 +1784,14 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
zoneId, aclType, subdomainAccess, vpcId, ip6Gateway, ip6Cidr, displayNetwork, isolatedPvlan, isolatedPvlanType, externalId, routerIp, routerIpv6);
}
if (_accountMgr.isRootAdmin(caller.getId()) && createVlan && network != null) {
if (createVlan && network != null) {
// Create vlan ip range
_configMgr.createVlanAndPublicIpRange(pNtwk.getDataCenterId(), network.getId(), physicalNetworkId, false, false, null, startIP, endIP, gateway, netmask, vlanId,
bypassVlanOverlapCheck, null, null, startIPv6, endIPv6, ip6Gateway, ip6Cidr);
}
if (associatedNetwork != null) {
_networkDetailsDao.persist(new NetworkDetailVO(network.getId(), Network.AssociatedNetworkId, String.valueOf(associatedNetwork.getId()), true));
}
return network;
}
});
@ -1733,6 +1840,13 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
Boolean forVpc = cmd.getForVpc();
Boolean display = cmd.getDisplay();
Long networkOfferingId = cmd.getNetworkOfferingId();
Long associatedNetworkId = cmd.getAssociatedNetworkId();
String networkFilterStr = cmd.getNetworkFilter();
String vlanId = null;
if (cmd instanceof ListNetworksCmdByAdmin) {
vlanId = ((ListNetworksCmdByAdmin)cmd).getVlan();
}
// 1) default is system to false if not specified
// 2) reset parameter to false if it's specified by a non-ROOT user
@ -1740,6 +1854,12 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
isSystem = false;
}
// check network filter
if (networkFilterStr != null && !EnumUtils.isValidEnumIgnoreCase(Network.NetworkFilter.class, networkFilterStr)) {
throw new InvalidParameterValueException("Invalid value of networkfilter: " + networkFilterStr);
}
Network.NetworkFilter networkFilter = networkFilterStr != null ? EnumUtils.getEnumIgnoreCase(Network.NetworkFilter.class, networkFilterStr) : Network.NetworkFilter.All;
// Account/domainId parameters and isSystem are mutually exclusive
if (isSystem != null && isSystem && (accountName != null || domainId != null)) {
throw new InvalidParameterValueException("System network belongs to system, account and domainId parameters can't be specified");
@ -1856,34 +1976,60 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
sb.join("accountSearch", accountSearch, sb.entity().getAccountId(), accountSearch.entity().getId(), JoinBuilder.JoinType.INNER);
if (associatedNetworkId != null) {
SearchBuilder<NetworkDetailVO> associatedNetworkSearch = _networkDetailsDao.createSearchBuilder();
associatedNetworkSearch.and("name", associatedNetworkSearch.entity().getName(), SearchCriteria.Op.EQ);
associatedNetworkSearch.and("value", associatedNetworkSearch.entity().getValue(), SearchCriteria.Op.EQ);
sb.join("associatedNetworkSearch", associatedNetworkSearch, sb.entity().getId(), associatedNetworkSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER);
}
List<NetworkVO> networksToReturn = new ArrayList<NetworkVO>();
if (isSystem == null || !isSystem) {
if (!permittedAccounts.isEmpty()) {
//get account level networks
networksToReturn.addAll(listAccountSpecificNetworks(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, networkOfferingId,
aclType, skipProjectNetworks, restartRequired, specifyIpRanges, vpcId, tags, display), searchFilter, permittedAccounts));
//get domain level networks
if (domainId != null) {
if (Arrays.asList(Network.NetworkFilter.Account, Network.NetworkFilter.AccountDomain, Network.NetworkFilter.All).contains(networkFilter)) {
//get account level networks
networksToReturn.addAll(listAccountSpecificNetworks(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, networkOfferingId,
aclType, skipProjectNetworks, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter, permittedAccounts));
}
if (domainId != null && Arrays.asList(Network.NetworkFilter.Domain, Network.NetworkFilter.AccountDomain, Network.NetworkFilter.All).contains(networkFilter)) {
//get domain level networks
networksToReturn.addAll(listDomainLevelNetworks(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, networkOfferingId,
aclType, true, restartRequired, specifyIpRanges, vpcId, tags, display), searchFilter, domainId, false));
aclType, true, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter, domainId, false));
}
if (Arrays.asList(Network.NetworkFilter.Shared, Network.NetworkFilter.All).contains(networkFilter)) {
// get shared networks
List<NetworkVO> sharedNetworks = listSharedNetworks(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, networkOfferingId,
aclType, skipProjectNetworks, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter, permittedAccounts);
addNetworksToReturnIfNotExist(networksToReturn, sharedNetworks);
}
} else {
//add account specific networks
networksToReturn.addAll(listAccountSpecificNetworksByDomainPath(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, networkOfferingId,
aclType, skipProjectNetworks, restartRequired, specifyIpRanges, vpcId, tags, display), searchFilter, path, isRecursive));
//add domain specific networks of domain + parent domains
networksToReturn.addAll(listDomainSpecificNetworksByDomainPath(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, networkOfferingId,
aclType, skipProjectNetworks, restartRequired, specifyIpRanges, vpcId, tags, display), searchFilter, path, isRecursive));
//add networks of subdomains
if (domainId == null) {
networksToReturn.addAll(listDomainLevelNetworks(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, networkOfferingId,
aclType, true, restartRequired, specifyIpRanges, vpcId, tags, display), searchFilter, caller.getDomainId(), true));
if (Arrays.asList(Network.NetworkFilter.Account, Network.NetworkFilter.AccountDomain, Network.NetworkFilter.All).contains(networkFilter)) {
//add account specific networks
networksToReturn.addAll(listAccountSpecificNetworksByDomainPath(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, networkOfferingId,
aclType, skipProjectNetworks, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter, path, isRecursive));
}
if (Arrays.asList(Network.NetworkFilter.Domain, Network.NetworkFilter.AccountDomain, Network.NetworkFilter.All).contains(networkFilter)) {
//add domain specific networks of domain + parent domains
networksToReturn.addAll(listDomainSpecificNetworksByDomainPath(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, networkOfferingId,
aclType, skipProjectNetworks, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter, path, isRecursive));
//add networks of subdomains
if (domainId == null) {
networksToReturn.addAll(listDomainLevelNetworks(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, networkOfferingId,
aclType, true, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter, caller.getDomainId(), true));
}
}
if (Arrays.asList(Network.NetworkFilter.Shared, Network.NetworkFilter.All).contains(networkFilter)) {
// get shared networks
List<NetworkVO> sharedNetworks = listSharedNetworksByDomainPath(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, networkOfferingId,
aclType, skipProjectNetworks, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter, path, isRecursive);
addNetworksToReturnIfNotExist(networksToReturn, sharedNetworks);
}
}
} else {
networksToReturn = _networksDao.search(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, networkOfferingId,
null, skipProjectNetworks, restartRequired, specifyIpRanges, vpcId, tags, display), searchFilter);
null, skipProjectNetworks, restartRequired, specifyIpRanges, vpcId, tags, display, vlanId, associatedNetworkId), searchFilter);
}
if (supportedServicesStr != null && !supportedServicesStr.isEmpty() && !networksToReturn.isEmpty()) {
@ -1930,10 +2076,20 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
return new Pair<List<? extends Network>, Integer>(networksToReturn, networksToReturn.size());
}
private void addNetworksToReturnIfNotExist(final List<NetworkVO> networksToReturn, final List<NetworkVO> sharedNetworks) {
Set<Long> networkIds = networksToReturn.stream()
.map(NetworkVO::getId)
.collect(Collectors.toSet());
List<NetworkVO> sharedNetworksToReturn = sharedNetworks.stream()
.filter(network -> ! networkIds.contains(network.getId()))
.collect(Collectors.toList());
networksToReturn.addAll(sharedNetworksToReturn);
}
private SearchCriteria<NetworkVO> buildNetworkSearchCriteria(SearchBuilder<NetworkVO> sb, String keyword, Long id,
Boolean isSystem, Long zoneId, String guestIpType, String trafficType, Long physicalNetworkId,
Long networkOfferingId, String aclType, boolean skipProjectNetworks, Boolean restartRequired,
Boolean specifyIpRanges, Long vpcId, Map<String, String> tags, Boolean display) {
Boolean specifyIpRanges, Long vpcId, Map<String, String> tags, Boolean display, String vlanId, Long associatedNetworkId) {
SearchCriteria<NetworkVO> sc = sb.create();
@ -2007,6 +2163,17 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
sc.addAnd("networkOfferingId", SearchCriteria.Op.EQ, networkOfferingId);
}
if (associatedNetworkId != null) {
sc.setJoinParameters("associatedNetworkSearch", "name", Network.AssociatedNetworkId);
sc.setJoinParameters("associatedNetworkSearch", "value", String.valueOf(associatedNetworkId));
}
if (vlanId != null) {
SearchCriteria<NetworkVO> ssc = _networksDao.createSearchCriteria();
ssc.addOr("broadcastUri", SearchCriteria.Op.EQ, vlanId);
ssc.addOr("broadcastUri", SearchCriteria.Op.LIKE, "%://" + vlanId);
sc.addAnd("broadcastUri", SearchCriteria.Op.SC, ssc);
}
return sc;
}
@ -2097,6 +2264,49 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
}
}
private List<NetworkVO> listSharedNetworks(SearchCriteria<NetworkVO> sc, Filter searchFilter, List<Long> permittedAccounts) {
List<Long> sharedNetworkIds = _networkPermissionDao.listPermittedNetworkIdsByAccounts(permittedAccounts);
if (!sharedNetworkIds.isEmpty()) {
SearchCriteria<NetworkVO> ssc = _networksDao.createSearchCriteria();
ssc.addAnd("id", SearchCriteria.Op.IN, sharedNetworkIds.toArray());
sc.addAnd("id", SearchCriteria.Op.SC, ssc);
return _networksDao.search(sc, searchFilter);
}
return new ArrayList<NetworkVO>();
}
private List<NetworkVO> listSharedNetworksByDomainPath(SearchCriteria<NetworkVO> sc, Filter searchFilter, String path, boolean isRecursive) {
Set<Long> allowedDomains = new HashSet<Long>();
if (path != null) {
if (isRecursive) {
allowedDomains = _domainMgr.getDomainChildrenIds(path);
} else {
Domain domain = _domainDao.findDomainByPath(path);
allowedDomains.add(domain.getId());
}
}
List<Long> allowedDomainsList = new ArrayList<Long>(allowedDomains);
if (!allowedDomainsList.isEmpty()) {
GenericSearchBuilder<AccountVO, Long> accountIdSearch = _accountDao.createSearchBuilder(Long.class);
accountIdSearch.and("domainId", accountIdSearch.entity().getDomainId(), SearchCriteria.Op.IN);
accountIdSearch.selectFields(accountIdSearch.entity().getId());
accountIdSearch.done();
SearchCriteria<Long> scAccount = accountIdSearch.create();
scAccount.setParameters("domainId", allowedDomainsList.toArray());
List<Long> allowedAccountsList = _accountDao.customSearch(scAccount, null);
List<Long> sharedNetworkIds = _networkPermissionDao.listPermittedNetworkIdsByAccounts(allowedAccountsList);
if (!sharedNetworkIds.isEmpty()) {
SearchCriteria<NetworkVO> ssc = _networksDao.createSearchCriteria();
ssc.addAnd("id", SearchCriteria.Op.IN, sharedNetworkIds.toArray());
sc.addAnd("id", SearchCriteria.Op.SC, ssc);
return _networksDao.search(sc, searchFilter);
}
}
return new ArrayList<NetworkVO>();
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_NETWORK_DELETE, eventDescription = "deleting network", async = true)
public boolean deleteNetwork(long networkId, boolean forced) {
@ -2111,15 +2321,17 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
throwInvalidIdException("Network with specified id is system and can't be removed", network.getUuid(), "networkId");
}
Account owner = _accountMgr.getAccount(network.getAccountId());
// Only Admin can delete Shared networks
if ((network.getGuestType() == GuestType.Shared) && !_accountMgr.isAdmin(caller.getId())) {
throw new InvalidParameterValueException("Only Admins can delete network with guest type " + network.getGuestType());
List<NetworkDetailVO> associatedNetworks = _networkDetailsDao.findDetails(Network.AssociatedNetworkId, String.valueOf(networkId), null);
for (NetworkDetailVO networkDetailVO : associatedNetworks) {
NetworkVO associatedNetwork = _networksDao.findById(networkDetailVO.getResourceId());
if (associatedNetwork != null) {
String msg = String.format("Cannot delete network %s which is associated to another network %s", network.getUuid(), associatedNetwork.getUuid());
s_logger.debug(msg);
throw new InvalidParameterValueException(msg);
}
}
// Perform permission check
_accountMgr.checkAccess(caller, null, true, network);
Account owner = _accountMgr.getAccount(network.getAccountId());
if (forced && !_accountMgr.isRootAdmin(caller.getId())) {
throw new InvalidParameterValueException("Delete network with 'forced' option can only be called by root admins");
@ -2164,7 +2376,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
}
Account callerAccount = _accountMgr.getActiveAccountById(user.getAccountId());
_accountMgr.checkAccess(callerAccount, null, true, network);
_accountMgr.checkAccess(callerAccount, AccessType.OperateEntry, true, network);
if (!network.isRedundant() && makeRedundant) {
network.setRedundant(true);
if (!_networksDao.update(network.getId(), network)) {
@ -2356,7 +2568,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
throw new InvalidParameterValueException("Can't allow networks which traffic type is not " + TrafficType.Guest);
}
_accountMgr.checkAccess(callerAccount, null, true, network);
_accountMgr.checkAccess(callerAccount, AccessType.OperateEntry, true, network);
_accountMgr.checkAccess(_accountMgr.getActiveAccountById(network.getAccountId()), offering, _dcDao.findById(network.getDataCenterId()));
if (cmd instanceof UpdateNetworkCmdByAdmin) {
@ -3367,7 +3579,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
removeVnets = getVnetsToremove(network, vnetranges);
//computing vnets to add
vnetsInDb.addAll(_datacneterVnet.listVnetsByPhysicalNetworkAndDataCenter(network.getDataCenterId(), network.getId()));
vnetsInDb.addAll(_dcVnetDao.listVnetsByPhysicalNetworkAndDataCenter(network.getDataCenterId(), network.getId()));
tempVnets.addAll(vnetsInDb);
for (Pair<Integer, Integer> vlan : vnetranges) {
for (i = vlan.first(); i <= vlan.second(); i++) {
@ -3409,7 +3621,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
s_logger.debug("removing vnet range " + removeVnetsFinal.toString() + " for the physicalNetwork id= " + network.getId() + " and zone id=" + network.getDataCenterId()
+ " as a part of updatePhysicalNetwork call");
//deleteVnets takes a list of strings to be removed. each string is a vnet.
_datacneterVnet.deleteVnets(TransactionLegacy.currentTxn(), network.getDataCenterId(), network.getId(), removeVnetsFinal);
_dcVnetDao.deleteVnets(TransactionLegacy.currentTxn(), network.getDataCenterId(), network.getId(), removeVnetsFinal);
}
_physicalNetworkDao.update(network.getId(), network);
}
@ -3445,7 +3657,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
// since adding a range adds each VNI to the database, need only check min/max
for (String vnet : VnetRange) {
s_logger.debug("Looking to see if VNI " + vnet + " already exists on another network in zone " + network.getDataCenterId());
List<DataCenterVnetVO> vnis = _datacneterVnet.findVnet(network.getDataCenterId(), vnet);
List<DataCenterVnetVO> vnis = _dcVnetDao.findVnet(network.getDataCenterId(), vnet);
if (vnis != null && !vnis.isEmpty()) {
for (DataCenterVnetVO vni : vnis) {
if (vni.getPhysicalNetworkId() != network.getId()) {
@ -3517,13 +3729,13 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
int i;
List<String> removeVnets = new ArrayList<String>();
HashSet<String> vnetsInDb = new HashSet<String>();
vnetsInDb.addAll(_datacneterVnet.listVnetsByPhysicalNetworkAndDataCenter(network.getDataCenterId(), network.getId()));
vnetsInDb.addAll(_dcVnetDao.listVnetsByPhysicalNetworkAndDataCenter(network.getDataCenterId(), network.getId()));
//remove all the vnets from vnets in db to check if there are any vnets that are not there in given list.
//remove all the vnets not in the list of vnets passed by the user.
if (vnetRanges.size() == 0) {
//this implies remove all vlans.
removeVnets.addAll(vnetsInDb);
int allocated_vnets = _datacneterVnet.countAllocatedVnets(network.getId());
int allocated_vnets = _dcVnetDao.countAllocatedVnets(network.getId());
if (allocated_vnets > 0) {
throw new InvalidParameterValueException("physicalnetwork " + network.getId() + " has " + allocated_vnets + " vnets in use");
}
@ -3546,8 +3758,8 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
String[] range = vnet.split("-");
Integer start = Integer.parseInt(range[0]);
Integer end = Integer.parseInt(range[1]);
_datacneterVnet.lockRange(network.getDataCenterId(), network.getId(), start, end);
List<DataCenterVnetVO> result = _datacneterVnet.listAllocatedVnetsInRange(network.getDataCenterId(), network.getId(), start, end);
_dcVnetDao.lockRange(network.getDataCenterId(), network.getId(), start, end);
List<DataCenterVnetVO> result = _dcVnetDao.listAllocatedVnetsInRange(network.getDataCenterId(), network.getId(), start, end);
if (!result.isEmpty()) {
throw new InvalidParameterValueException("physicalnetwork " + network.getId() + " has allocated vnets in the range " + start + "-" + end);
@ -3696,7 +3908,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
@Override
@DB
@ActionEvent(eventType = EventTypes.EVENT_GUEST_VLAN_RANGE_DEDICATE, eventDescription = "dedicating guest vlan range", async = false)
public GuestVlan dedicateGuestVlanRange(DedicateGuestVlanRangeCmd cmd) {
public GuestVlanRange dedicateGuestVlanRange(DedicateGuestVlanRangeCmd cmd) {
String vlan = cmd.getVlan();
String accountName = cmd.getAccountName();
Long domainId = cmd.getDomainId();
@ -3771,7 +3983,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
// Verify guest vlans in the range don't belong to a network of a different account
for (int i = startVlan; i <= endVlan; i++) {
List<DataCenterVnetVO> allocatedVlans = _datacneterVnet.listAllocatedVnetsInRange(physicalNetwork.getDataCenterId(), physicalNetwork.getId(), startVlan, endVlan);
List<DataCenterVnetVO> allocatedVlans = _dcVnetDao.listAllocatedVnetsInRange(physicalNetwork.getDataCenterId(), physicalNetwork.getId(), startVlan, endVlan);
if (allocatedVlans != null && !allocatedVlans.isEmpty()) {
for (DataCenterVnetVO allocatedVlan : allocatedVlans) {
if (allocatedVlan.getAccountId() != vlanOwner.getAccountId()) {
@ -3821,7 +4033,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
List<Integer> vlanTokens2 = getVlanFromRange(guestVlanMaps.get(i + 1).getGuestVlanRange());
// Range extends 2 vlan ranges, both to the right and left
if (endVlan == (vlanTokens2.get(0).intValue() - 1) && guestVlanMaps.get(i + 1).getAccountId() == vlanOwnerId) {
_datacneterVnet.releaseDedicatedGuestVlans(guestVlanMaps.get(i + 1).getId());
_dcVnetDao.releaseDedicatedGuestVlans(guestVlanMaps.get(i + 1).getId());
_accountGuestVlanMapDao.remove(guestVlanMaps.get(i + 1).getId());
updatedVlanRange = vlanTokens1.get(0).intValue() + "-" + vlanTokens2.get(1).intValue();
break;
@ -3845,9 +4057,9 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
// For every guest vlan set the corresponding account guest vlan map id
List<Integer> finaVlanTokens = getVlanFromRange(accountGuestVlanMapVO.getGuestVlanRange());
for (int i = finaVlanTokens.get(0).intValue(); i <= finaVlanTokens.get(1).intValue(); i++) {
List<DataCenterVnetVO> dataCenterVnet = _datacneterVnet.findVnet(physicalNetwork.getDataCenterId(), physicalNetworkId, Integer.toString(i));
List<DataCenterVnetVO> dataCenterVnet = _dcVnetDao.findVnet(physicalNetwork.getDataCenterId(), physicalNetworkId, Integer.toString(i));
dataCenterVnet.get(0).setAccountGuestVlanMapId(accountGuestVlanMapVO.getId());
_datacneterVnet.update(dataCenterVnet.get(0).getId(), dataCenterVnet.get(0));
_dcVnetDao.update(dataCenterVnet.get(0).getId(), dataCenterVnet.get(0));
}
return accountGuestVlanMapVO;
}
@ -3869,7 +4081,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
}
@Override
public Pair<List<? extends GuestVlan>, Integer> listDedicatedGuestVlanRanges(ListDedicatedGuestVlanRangesCmd cmd) {
public Pair<List<? extends GuestVlanRange>, Integer> listDedicatedGuestVlanRanges(ListDedicatedGuestVlanRangesCmd cmd) {
Long id = cmd.getId();
String accountName = cmd.getAccountName();
Long domainId = cmd.getDomainId();
@ -3942,7 +4154,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
Filter searchFilter = new Filter(AccountGuestVlanMapVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
Pair<List<AccountGuestVlanMapVO>, Integer> result = _accountGuestVlanMapDao.searchAndCount(sc, searchFilter);
return new Pair<List<? extends GuestVlan>, Integer>(result.first(), result.second());
return new Pair<List<? extends GuestVlanRange>, Integer>(result.first(), result.second());
}
@Override
@ -3956,7 +4168,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
}
// Remove dedication for the guest vlan
_datacneterVnet.releaseDedicatedGuestVlans(dedicatedGuestVlan.getId());
_dcVnetDao.releaseDedicatedGuestVlans(dedicatedGuestVlan.getId());
if (_accountGuestVlanMapDao.remove(dedicatedGuestVlanRangeId)) {
return true;
} else {
@ -4646,9 +4858,10 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
@Override
@DB
public Network createPrivateNetwork(final String networkName, final String displayText, long physicalNetworkId, String broadcastUriString, final String startIp, String endIp, final String gateway,
String netmask, final long networkOwnerId, final Long vpcId, final Boolean sourceNat, final Long networkOfferingId, final Boolean bypassVlanOverlapCheck)
String netmask, final long networkOwnerId, final Long vpcId, final Boolean sourceNat, final Long networkOfferingId, final Boolean bypassVlanOverlapCheck, final Long associatedNetworkId)
throws ResourceAllocationException, ConcurrentOperationException, InsufficientCapacityException {
final Account caller = CallContext.current().getCallingAccount();
final Account owner = _accountMgr.getAccount(networkOwnerId);
// Get system network offering
@ -4686,13 +4899,22 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
final String cidr = NetUtils.ipAndNetMaskToCidr(gateway, netmask);
URI uri = BroadcastDomainType.fromString(broadcastUriString);
final String uriString = uri.toString();
BroadcastDomainType tiep = BroadcastDomainType.getSchemeValue(uri);
// numeric vlan or vlan uri are ok for now
// TODO make a test for any supported scheme
if (!(tiep == BroadcastDomainType.Vlan || tiep == BroadcastDomainType.Lswitch)) {
throw new InvalidParameterValueException("unsupported type of broadcastUri specified: " + broadcastUriString);
final String uriString;
if (broadcastUriString != null) {
URI uri = BroadcastDomainType.fromString(broadcastUriString);
uriString = uri.toString();
BroadcastDomainType tiep = BroadcastDomainType.getSchemeValue(uri);
// numeric vlan or vlan uri are ok for now
// TODO make a test for any supported scheme
if (!(tiep == BroadcastDomainType.Vlan || tiep == BroadcastDomainType.Lswitch)) {
throw new InvalidParameterValueException("unsupported type of broadcastUri specified: " + broadcastUriString);
}
} else if (associatedNetworkId != null) {
DataCenter zone = _dcDao.findById(pNtwk.getDataCenterId());
Network associatedNetwork = implementAssociatedNetwork(associatedNetworkId, caller, owner, zone, null, owner.getAccountId(), cidr, startIp, endIp);
uriString = associatedNetwork.getBroadcastUri().toString();
} else {
throw new InvalidParameterValueException("One of uri and associatedNetworkId must be passed");
}
final NetworkOfferingVO ntwkOffFinal = ntwkOff;
@ -4710,6 +4932,9 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
privateNetwork = _networkMgr.createPrivateNetwork(ntwkOffFinal.getId(), networkName, displayText, gateway, cidr, uriString, bypassVlanOverlapCheck, owner, pNtwk, vpcId);
if (privateNetwork != null) {
s_logger.debug("Successfully created guest network " + privateNetwork);
if (associatedNetworkId != null) {
_networkDetailsDao.persist(new NetworkDetailVO(privateNetwork.getId(), Network.AssociatedNetworkId, String.valueOf(associatedNetworkId), true));
}
} else {
throw new CloudRuntimeException("Creating guest network failed");
}
@ -4858,6 +5083,210 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
return true;
}
@Override
public Pair<List<? extends GuestVlan>, Integer> listGuestVlans(ListGuestVlansCmd cmd) {
Long id = cmd.getId();
Long zoneId = cmd.getZoneId();
Long physicalNetworkId = cmd.getPhysicalNetworkId();
String vnet = cmd.getVnet();
Boolean allocatedOnly = cmd.getAllocatedOnly();
String keyword = cmd.getKeyword();
SearchCriteria<DataCenterVnetVO> vlanSearch = _dcVnetDao.createSearchCriteria();
if (id != null) {
vlanSearch.addAnd("id", Op.EQ, id);
}
if (zoneId != null) {
vlanSearch.addAnd("dataCenterId", Op.EQ, zoneId);
}
if (physicalNetworkId != null) {
vlanSearch.addAnd("physicalNetworkId", Op.EQ, physicalNetworkId);
}
if (vnet != null) {
vlanSearch.addAnd("vnet", Op.EQ, vnet);
}
if (allocatedOnly != null && allocatedOnly) {
vlanSearch.addAnd("takenAt", Op.NNULL);
}
if (keyword != null) {
vlanSearch.addAnd("vnet", Op.LIKE, "%" + keyword + "%");
}
Long pageSizeVal = cmd.getPageSizeVal();
Long startIndex = cmd.getStartIndex();
Filter searchFilter = new Filter(DataCenterVnetVO.class, "vnet", true, startIndex, pageSizeVal);
Pair<List<DataCenterVnetVO>, Integer> vlans = _dcVnetDao.searchAndCount(vlanSearch, searchFilter);
return new Pair<List<? extends GuestVlan>, Integer>(vlans.first(), vlans.second());
}
@Override
public List<? extends NetworkPermission> listNetworkPermissions(ListNetworkPermissionsCmd cmd) {
final Long networkId = cmd.getNetworkId();
NetworkVO network = _networksDao.findById(networkId);
if (network == null) {
throw new InvalidParameterValueException("unable to find network with id " + networkId);
}
final Account caller = CallContext.current().getCallingAccount();
_accountMgr.checkAccess(caller, AccessType.OperateEntry, true, network);
List<String> accountNames = new ArrayList<String>();
List<NetworkPermissionVO> permissions = _networkPermissionDao.findByNetwork(networkId);
return permissions;
}
@Override
public boolean createNetworkPermissions(CreateNetworkPermissionsCmd cmd) {
final Long id = cmd.getNetworkId();
List<String> accountNames = cmd.getAccountNames();
List<Long> accountIds = cmd.getAccountIds();
List<Long> projectIds = cmd.getProjectIds();
final Account caller = CallContext.current().getCallingAccount();
NetworkVO network = validateNetworkPermissionParameters(caller, id);
accountIds = populateAccounts(caller, accountIds, network.getDomainId(), accountNames, projectIds);
final List<Long> accountIdsFinal = accountIds;
final Account owner = _accountMgr.getAccount(network.getAccountId());
Transaction.execute(new TransactionCallbackNoReturn() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) {
for (Long accountId : accountIdsFinal) {
Account permittedAccount = _accountDao.findActiveAccountById(accountId, network.getDomainId());
if (permittedAccount != null) {
if (permittedAccount.getId() == owner.getId()) {
continue; // don't grant permission to the network owner, they implicitly have permission
}
NetworkPermissionVO existingPermission = _networkPermissionDao.findByNetworkAndAccount(id, permittedAccount.getId());
if (existingPermission == null) {
NetworkPermissionVO networkPermission = new NetworkPermissionVO(id, permittedAccount.getId());
_networkPermissionDao.persist(networkPermission);
}
} else {
throw new InvalidParameterValueException("Unable to find account " + accountId + " in the domain of network " + network + ". No permissions is added");
}
}
}
});
return true;
}
@Override
public boolean removeNetworkPermissions(RemoveNetworkPermissionsCmd cmd) {
final Long id = cmd.getNetworkId();
List<String> accountNames = cmd.getAccountNames();
List<Long> accountIds = cmd.getAccountIds();
List<Long> projectIds = cmd.getProjectIds();
final Account caller = CallContext.current().getCallingAccount();
NetworkVO network = validateNetworkPermissionParameters(caller, id);
accountIds = populateAccounts(caller, accountIds, network.getDomainId(), accountNames, projectIds);
_networkPermissionDao.removePermissions(id, accountIds);
return true;
}
@Override
public boolean resetNetworkPermissions(ResetNetworkPermissionsCmd cmd) {
final Long id = cmd.getNetworkId();
final Account caller = CallContext.current().getCallingAccount();
NetworkVO network = validateNetworkPermissionParameters(caller, id);
_networkPermissionDao.removeAllPermissions(id);
return true;
}
private NetworkVO validateNetworkPermissionParameters(Account caller, Long id) {
final NetworkVO network = _networksDao.findById(id);
if (network == null) {
throw new InvalidParameterValueException("unable to find network with id " + id);
}
if (network.getAclType() == ACLType.Domain) {
throw new InvalidParameterValueException("network is already shared in domain");
}
if (network.getVpcId() != null) {
throw new InvalidParameterValueException("VPC tiers cannot be shared");
}
_accountMgr.checkAccess(caller, AccessType.OperateEntry, true, network);
final Account owner = _accountMgr.getAccount(network.getAccountId());
if (owner.getType() == Account.Type.PROJECT) {
// Currently project owned networks cannot be shared outside project but is available to all users within project by default.
throw new InvalidParameterValueException("Update network permissions is an invalid operation on network " + network.getName()
+ ". Project owned networks cannot be shared outside network.");
}
//Only admin or owner of the network should be able to change its permissions
if (caller.getId() != owner.getId() && !_accountMgr.isAdmin(caller.getId())) {
throw new InvalidParameterValueException("Unable to grant permission to account " + caller.getAccountName() + " as it is neither admin nor owner or the network");
}
return network;
}
private List<Long> populateAccounts(Account caller, List<Long> accountIds, Long domainId, List<String> accountNames, List<Long> projectIds) {
if (accountIds == null) {
accountIds = new ArrayList<Long>();
}
// convert projectIds to accountIds
if (projectIds != null) {
accountIds.addAll(convertProjectIdsToAccountIds(caller, projectIds));
}
// convert accountNames to accountIds
if (accountNames != null) {
accountIds.addAll(convertAccountNamesToAccountIds(caller, domainId, accountNames));
}
final Domain domain = _domainDao.findById(domainId);
for (Long accountId : accountIds) {
Account permittedAccount = _accountDao.findActiveAccountById(accountId, domain.getId());
if (permittedAccount == null) {
throw new InvalidParameterValueException("Unable to find account " + accountId + " in domain id=" + domain.getUuid() + ". No permissions is removed");
}
}
return accountIds;
}
private List<Long> convertProjectIdsToAccountIds(final Account caller, final List<Long> projectIds) {
List<Long> accountIds = new ArrayList<Long>();
for (Long projectId : projectIds) {
Project project = _projectMgr.getProject(projectId);
if (project == null) {
throw new InvalidParameterValueException("Unable to find project by id " + projectId);
}
if (!_projectMgr.canAccessProjectAccount(caller, project.getProjectAccountId())) {
throw new InvalidParameterValueException("Account " + caller + " can't access project id=" + projectId);
}
accountIds.add(project.getProjectAccountId());
}
return accountIds;
}
private List<Long> convertAccountNamesToAccountIds(final Account caller, final Long domainId, final List<String> accountNames) {
List<Long> accountIds = new ArrayList<Long>();
for (String accountName : accountNames) {
Account permittedAccount = _accountDao.findActiveAccount(accountName, domainId);
if (permittedAccount == null) {
throw new InvalidParameterValueException("Unable to find account by name " + accountName);
}
if (permittedAccount.getId() != caller.getId()) {
accountIds.add(permittedAccount.getId());
}
}
return accountIds;
}
@Override
public String getConfigComponentName() {
return NetworkService.class.getSimpleName();

View File

@ -112,7 +112,7 @@ public abstract class GuestNetworkGuru extends AdapterBase implements NetworkGur
IpAddressManager _ipAddrMgr;
Random _rand = new Random(System.currentTimeMillis());
static final ConfigKey<Boolean> UseSystemGuestVlans =
public static final ConfigKey<Boolean> UseSystemGuestVlans =
new ConfigKey<Boolean>(
"Advanced",
Boolean.class,

View File

@ -124,7 +124,7 @@ public class PrivateNetworkGuru extends AdapterBase implements NetworkGuru {
throw new InvalidParameterValueException("Can't design network " + network + "; netmask/gateway must be passed in");
}
if (offering.isSpecifyVlan()) {
if (userSpecified.getBroadcastUri() != null) {
network.setBroadcastUri(userSpecified.getBroadcastUri());
network.setState(State.Setup);
}

View File

@ -31,6 +31,7 @@ import javax.inject.Inject;
import com.cloud.offerings.NetworkOfferingServiceMapVO;
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
import org.apache.cloudstack.acl.SecurityChecker;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.command.user.loadbalancer.CreateLBHealthCheckPolicyCmd;
import org.apache.cloudstack.api.command.user.loadbalancer.CreateLBStickinessPolicyCmd;
@ -1011,9 +1012,9 @@ public class LoadBalancingRulesManagerImpl<Type> extends ManagerBase implements
_rulesMgr.checkRuleAndUserVm(loadBalancer, vm, caller);
if (vm.getAccountId() != loadBalancer.getAccountId()) {
throw new PermissionDeniedException("Cannot add virtual machines that do not belong to the same owner.");
}
Account vmOwner = _accountDao.findById(vm.getAccountId());
Network network = _networkDao.findById(loadBalancer.getNetworkId());
_accountMgr.checkAccess(vmOwner, SecurityChecker.AccessType.UseEntry, false, network);
// Let's check to make sure the vm has a nic in the same network as
// the load balancing rule.

View File

@ -31,6 +31,7 @@ import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.vm.NicProfile;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.VirtualMachineProfileImpl;
import org.apache.cloudstack.acl.SecurityChecker;
import org.apache.cloudstack.api.command.user.firewall.ListPortForwardingRulesCmd;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
@ -170,13 +171,7 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
}
}
_accountMgr.checkAccess(caller, null, true, ipAddress, userVm);
// validate that IP address and userVM belong to the same account
if (ipAddress.getAllocatedToAccountId().longValue() != userVm.getAccountId()) {
throw new InvalidParameterValueException("Unable to create ip forwarding rule, IP address " + ipAddress +
" owner is not the same as owner of virtual machine " + userVm.toString());
}
_accountMgr.checkAccess(caller, null, false, ipAddress, userVm);
// validate that userVM is in the same availability zone as the IP address
if (ipAddress.getDataCenterId() != userVm.getDataCenterId()) {
@ -195,16 +190,11 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
return;
}
_accountMgr.checkAccess(caller, null, true, rule, userVm);
_accountMgr.checkAccess(caller, null, false, rule, userVm);
if (userVm.getState() == VirtualMachine.State.Destroyed || userVm.getState() == VirtualMachine.State.Expunging) {
throw new InvalidParameterValueException("Invalid user vm: " + userVm.getId());
}
// This same owner check is actually not needed, since multiple entities OperateEntry trick guarantee that
if (rule.getAccountId() != userVm.getAccountId()) {
throw new InvalidParameterValueException("New rule " + rule + " and vm id=" + userVm.getId() + " belong to different accounts");
}
}
@Override
@ -571,6 +561,8 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
} else {
checkIpAndUserVm(ipAddress, vm, caller, false);
}
Account vmOwner = _accountMgr.getAccount(vm.getAccountId());
_accountMgr.checkAccess(vmOwner, SecurityChecker.AccessType.UseEntry, false, network);
//is static nat is for vm secondary ip
//dstIp = guestNic.getIp4Address();

View File

@ -43,8 +43,10 @@ import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.command.admin.vpc.CreatePrivateGatewayByAdminCmd;
import org.apache.cloudstack.api.command.admin.vpc.CreateVPCOfferingCmd;
import org.apache.cloudstack.api.command.admin.vpc.UpdateVPCOfferingCmd;
import org.apache.cloudstack.api.command.user.vpc.CreatePrivateGatewayCmd;
import org.apache.cloudstack.api.command.user.vpc.ListPrivateGatewaysCmd;
import org.apache.cloudstack.api.command.user.vpc.ListStaticRoutesCmd;
import org.apache.cloudstack.api.command.user.vpc.ListVPCOfferingsCmd;
@ -115,6 +117,8 @@ import com.cloud.network.vpc.dao.VpcServiceMapDao;
import com.cloud.network.vpn.Site2SiteVpnManager;
import com.cloud.offering.NetworkOffering;
import com.cloud.offerings.NetworkOfferingServiceMapVO;
import com.cloud.offerings.NetworkOfferingVO;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
import com.cloud.org.Grouping;
import com.cloud.projects.Project.ListProjectResourcesCriteria;
@ -225,6 +229,8 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
DomainDao domainDao;
@Inject
private AnnotationDao annotationDao;
@Inject
NetworkOfferingDao _networkOfferingDao;
@Inject
private VpcPrivateGatewayTransactionCallable vpcTxCallable;
@ -1821,8 +1827,29 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
@Override
@DB
@ActionEvent(eventType = EventTypes.EVENT_PRIVATE_GATEWAY_CREATE, eventDescription = "creating VPC private gateway", create = true)
public PrivateGateway createVpcPrivateGateway(final long vpcId, Long physicalNetworkId, final String broadcastUri, final String ipAddress, final String gateway,
final String netmask, final long gatewayOwnerId, final Long networkOfferingId, final Boolean isSourceNat, final Long aclId, final Boolean bypassVlanOverlapCheck) throws ResourceAllocationException,
public PrivateGateway createVpcPrivateGateway(CreatePrivateGatewayCmd command) throws ResourceAllocationException,
ConcurrentOperationException, InsufficientCapacityException {
long vpcId = command.getVpcId();
String ipAddress = command.getIpAddress();
String gateway = command.getGateway();
String netmask = command.getNetmask();
long gatewayOwnerId = command.getEntityOwnerId();
Long networkOfferingId = command.getNetworkOfferingId();
Boolean isSourceNat = command.getIsSourceNat();
Long aclId = command.getAclId();
Long associatedNetworkId = command.getAssociatedNetworkId();
if (command instanceof CreatePrivateGatewayByAdminCmd) {
Long physicalNetworkId = ((CreatePrivateGatewayByAdminCmd)command).getPhysicalNetworkId();
String broadcastUri = ((CreatePrivateGatewayByAdminCmd)command).getBroadcastUri();
Boolean bypassVlanOverlapCheck = ((CreatePrivateGatewayByAdminCmd)command).getBypassVlanOverlapCheck();
return createVpcPrivateGateway(vpcId, physicalNetworkId, broadcastUri, ipAddress, gateway, netmask, gatewayOwnerId, networkOfferingId, isSourceNat, aclId, bypassVlanOverlapCheck, associatedNetworkId);
}
return createVpcPrivateGateway(vpcId, null, null, ipAddress, gateway, netmask, gatewayOwnerId, networkOfferingId, isSourceNat, aclId, false, associatedNetworkId);
}
private PrivateGateway createVpcPrivateGateway(final long vpcId, Long physicalNetworkId, final String broadcastUri, final String ipAddress, final String gateway,
final String netmask, final long gatewayOwnerId, final Long networkOfferingIdPassed, final Boolean isSourceNat, final Long aclId, final Boolean bypassVlanOverlapCheck, final Long associatedNetworkId) throws ResourceAllocationException,
ConcurrentOperationException, InsufficientCapacityException {
// Validate parameters
@ -1833,105 +1860,91 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
throw ex;
}
PhysicalNetwork physNet = null;
// Validate physical network
if (physicalNetworkId == null) {
final List<? extends PhysicalNetwork> pNtwks = _ntwkModel.getPhysicalNtwksSupportingTrafficType(vpc.getZoneId(), TrafficType.Guest);
if (pNtwks.isEmpty() || pNtwks.size() != 1) {
throw new InvalidParameterValueException("Physical network can't be determined; pass physical network id");
}
physNet = pNtwks.get(0);
physicalNetworkId = physNet.getId();
}
NetworkOfferingVO ntwkOff = getVpcPrivateGatewayNetworkOffering(networkOfferingIdPassed, broadcastUri);
final Long networkOfferingId = ntwkOff.getId();
if (physNet == null) {
physNet = _entityMgr.findById(PhysicalNetwork.class, physicalNetworkId);
}
final Long dcId = physNet.getDataCenterId();
validateVpcPrivateGatewayAssociateNetworkId(ntwkOff, broadcastUri, associatedNetworkId, bypassVlanOverlapCheck);
final Long dcId = vpc.getZoneId();
physicalNetworkId = validateVpcPrivateGatewayPhysicalNetworkId(dcId, physicalNetworkId, associatedNetworkId, ntwkOff);
PhysicalNetwork physNet = _entityMgr.findById(PhysicalNetwork.class, physicalNetworkId);;
final Long physicalNetworkIdFinal = physicalNetworkId;
final PhysicalNetwork physNetFinal = physNet;
VpcGatewayVO gatewayVO = null;
try {
gatewayVO = Transaction.execute(new TransactionCallbackWithException<VpcGatewayVO, Exception>() {
@Override
public VpcGatewayVO doInTransaction(final TransactionStatus status) throws ResourceAllocationException, ConcurrentOperationException,
InsufficientCapacityException {
s_logger.debug("Creating Private gateway for VPC " + vpc);
// 1) create private network unless it is existing and
// lswitch'd
Network privateNtwk = null;
if (BroadcastDomainType.getSchemeValue(BroadcastDomainType.fromString(broadcastUri)) == BroadcastDomainType.Lswitch) {
final String cidr = NetUtils.ipAndNetMaskToCidr(gateway, netmask);
privateNtwk = _ntwkDao.getPrivateNetwork(broadcastUri, cidr, gatewayOwnerId, dcId, networkOfferingId, vpcId);
// if the dcid is different we get no network so next we
// try to create it
}
if (privateNtwk == null) {
s_logger.info("creating new network for vpc " + vpc + " using broadcast uri: " + broadcastUri);
final String networkName = "vpc-" + vpc.getName() + "-privateNetwork";
privateNtwk = _ntwkSvc.createPrivateNetwork(networkName, networkName, physicalNetworkIdFinal, broadcastUri, ipAddress, null, gateway, netmask,
gatewayOwnerId, vpcId, isSourceNat, networkOfferingId, bypassVlanOverlapCheck);
} else { // create the nic/ip as createPrivateNetwork
// doesn''t do that work for us now
s_logger.info("found and using existing network for vpc " + vpc + ": " + broadcastUri);
final DataCenterVO dc = _dcDao.lockRow(physNetFinal.getDataCenterId(), true);
s_logger.debug("Creating Private gateway for VPC " + vpc);
// 1) create private network unless it is existing and
// lswitch'd
Network privateNtwk = null;
if (broadcastUri != null
&& BroadcastDomainType.getSchemeValue(BroadcastDomainType.fromString(broadcastUri)) == BroadcastDomainType.Lswitch) {
final String cidr = NetUtils.ipAndNetMaskToCidr(gateway, netmask);
privateNtwk = _ntwkDao.getPrivateNetwork(broadcastUri, cidr, gatewayOwnerId, dcId, networkOfferingId, vpcId);
// if the dcid is different we get no network so next we
// try to create it
}
if (privateNtwk == null) {
s_logger.info("creating new network for vpc " + vpc + " using broadcast uri: " + broadcastUri + " and associated network id: " + associatedNetworkId);
final String networkName = "vpc-" + vpc.getName() + "-privateNetwork";
privateNtwk = _ntwkSvc.createPrivateNetwork(networkName, networkName, physicalNetworkIdFinal, broadcastUri, ipAddress, null, gateway, netmask,
gatewayOwnerId, vpcId, isSourceNat, networkOfferingId, bypassVlanOverlapCheck, associatedNetworkId);
} else { // create the nic/ip as createPrivateNetwork
// doesn''t do that work for us now
s_logger.info("found and using existing network for vpc " + vpc + ": " + broadcastUri);
final DataCenterVO dc = _dcDao.lockRow(physNetFinal.getDataCenterId(), true);
// add entry to private_ip_address table
PrivateIpVO privateIp = _privateIpDao.findByIpAndSourceNetworkId(privateNtwk.getId(), ipAddress);
if (privateIp != null) {
throw new InvalidParameterValueException("Private ip address " + ipAddress + " already used for private gateway" + " in zone "
+ _entityMgr.findById(DataCenter.class, dcId).getName());
}
final Long mac = dc.getMacAddress();
final Long nextMac = mac + 1;
dc.setMacAddress(nextMac);
s_logger.info("creating private ip address for vpc (" + ipAddress + ", " + privateNtwk.getId() + ", " + nextMac + ", " + vpcId + ", " + isSourceNat + ")");
privateIp = new PrivateIpVO(ipAddress, privateNtwk.getId(), nextMac, vpcId, isSourceNat);
_privateIpDao.persist(privateIp);
_dcDao.update(dc.getId(), dc);
}
long networkAclId = NetworkACL.DEFAULT_DENY;
if (aclId != null) {
final NetworkACLVO aclVO = _networkAclDao.findById(aclId);
if (aclVO == null) {
throw new InvalidParameterValueException("Invalid network acl id passed ");
}
if (aclVO.getVpcId() != vpcId && !(aclId == NetworkACL.DEFAULT_DENY || aclId == NetworkACL.DEFAULT_ALLOW)) {
throw new InvalidParameterValueException("Private gateway and network acl are not in the same vpc");
}
networkAclId = aclId;
}
{ // experimental block, this is a hack
// set vpc id in network to null
// might be needed for all types of broadcast domains
// the ugly hack is that vpc gateway nets are created as
// guest network
// while they are not.
// A more permanent solution would be to define a type of
// 'gatewaynetwork'
// so that handling code is not mixed between the two
final NetworkVO gatewaynet = _ntwkDao.findById(privateNtwk.getId());
gatewaynet.setVpcId(null);
_ntwkDao.persist(gatewaynet);
}
// 2) create gateway entry
final VpcGatewayVO gatewayVO = new VpcGatewayVO(ipAddress, VpcGateway.Type.Private, vpcId, privateNtwk.getDataCenterId(), privateNtwk.getId(), broadcastUri,
gateway, netmask, vpc.getAccountId(), vpc.getDomainId(), isSourceNat, networkAclId);
_vpcGatewayDao.persist(gatewayVO);
s_logger.debug("Created vpc gateway entry " + gatewayVO);
return gatewayVO;
// add entry to private_ip_address table
PrivateIpVO privateIp = _privateIpDao.findByIpAndSourceNetworkId(privateNtwk.getId(), ipAddress);
if (privateIp != null) {
throw new InvalidParameterValueException("Private ip address " + ipAddress + " already used for private gateway" + " in zone "
+ _entityMgr.findById(DataCenter.class, dcId).getName());
}
});
final Long mac = dc.getMacAddress();
final Long nextMac = mac + 1;
dc.setMacAddress(nextMac);
s_logger.info("creating private ip address for vpc (" + ipAddress + ", " + privateNtwk.getId() + ", " + nextMac + ", " + vpcId + ", " + isSourceNat + ")");
privateIp = new PrivateIpVO(ipAddress, privateNtwk.getId(), nextMac, vpcId, isSourceNat);
_privateIpDao.persist(privateIp);
_dcDao.update(dc.getId(), dc);
}
long networkAclId = NetworkACL.DEFAULT_DENY;
if (aclId != null) {
final NetworkACLVO aclVO = _networkAclDao.findById(aclId);
if (aclVO == null) {
throw new InvalidParameterValueException("Invalid network acl id passed ");
}
if (aclVO.getVpcId() != vpcId && !(aclId == NetworkACL.DEFAULT_DENY || aclId == NetworkACL.DEFAULT_ALLOW)) {
throw new InvalidParameterValueException("Private gateway and network acl are not in the same vpc");
}
networkAclId = aclId;
}
{ // experimental block, this is a hack
// set vpc id in network to null
// might be needed for all types of broadcast domains
// the ugly hack is that vpc gateway nets are created as
// guest network
// while they are not.
// A more permanent solution would be to define a type of
// 'gatewaynetwork'
// so that handling code is not mixed between the two
final NetworkVO gatewaynet = _ntwkDao.findById(privateNtwk.getId());
gatewaynet.setVpcId(null);
_ntwkDao.persist(gatewaynet);
}
// 2) create gateway entry
gatewayVO = new VpcGatewayVO(ipAddress, VpcGateway.Type.Private, vpcId, privateNtwk.getDataCenterId(), privateNtwk.getId(), privateNtwk.getBroadcastUri().toString(),
gateway, netmask, vpc.getAccountId(), vpc.getDomainId(), isSourceNat, networkAclId);
_vpcGatewayDao.persist(gatewayVO);
s_logger.debug("Created vpc gateway entry " + gatewayVO);
} catch (final Exception e) {
ExceptionUtil.rethrowRuntime(e);
ExceptionUtil.rethrow(e, InsufficientCapacityException.class);
@ -1943,6 +1956,75 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
return getVpcPrivateGateway(gatewayVO.getId());
}
private void validateVpcPrivateGatewayAssociateNetworkId(NetworkOfferingVO ntwkOff, String broadcastUri, Long associatedNetworkId, Boolean bypassVlanOverlapCheck) {
// Validate vlanId and associatedNetworkId
if (broadcastUri == null && associatedNetworkId == null) {
throw new InvalidParameterValueException("One of vlanId and associatedNetworkId must be specified");
}
if (broadcastUri != null && associatedNetworkId != null) {
throw new InvalidParameterValueException("vlanId and associatedNetworkId are mutually exclusive");
}
Account caller = CallContext.current().getCallingAccount();
if (!_accountMgr.isRootAdmin(caller.getId()) && (ntwkOff.isSpecifyVlan() || broadcastUri != null || bypassVlanOverlapCheck)) {
throw new InvalidParameterValueException("Only ROOT admin is allowed to specify vlanId or bypass vlan overlap check");
}
if (ntwkOff.isSpecifyVlan() && broadcastUri == null) {
throw new InvalidParameterValueException("vlanId must be specified for this network offering");
}
if (! ntwkOff.isSpecifyVlan() && associatedNetworkId == null) {
throw new InvalidParameterValueException("associatedNetworkId must be specified for this network offering");
}
}
private NetworkOfferingVO getVpcPrivateGatewayNetworkOffering(Long networkOfferingIdPassed, String broadcastUri) {
// Validate network offering
NetworkOfferingVO ntwkOff = null;
if (networkOfferingIdPassed != null) {
ntwkOff = _networkOfferingDao.findById(networkOfferingIdPassed);
if (ntwkOff == null) {
throw new InvalidParameterValueException("Unable to find network offering by id specified");
}
if (! TrafficType.Guest.equals(ntwkOff.getTrafficType())) {
throw new InvalidParameterValueException("The network offering cannot be used to create Guest network");
}
if (! GuestType.Isolated.equals(ntwkOff.getGuestType())) {
throw new InvalidParameterValueException("The network offering cannot be used to create Isolated network");
}
} else if (broadcastUri != null) {
ntwkOff = _networkOfferingDao.findByUniqueName(NetworkOffering.SystemPrivateGatewayNetworkOffering);
} else {
ntwkOff = _networkOfferingDao.findByUniqueName(NetworkOffering.SystemPrivateGatewayNetworkOfferingWithoutVlan);
}
return ntwkOff;
}
private Long validateVpcPrivateGatewayPhysicalNetworkId(Long dcId, Long physicalNetworkId, Long associatedNetworkId, NetworkOfferingVO ntwkOff) {
// Validate physical network
if (associatedNetworkId != null) {
Network associatedNetwork = _entityMgr.findById(Network.class, associatedNetworkId);
if (associatedNetwork == null) {
throw new InvalidParameterValueException("Unable to find network by ID " + associatedNetworkId);
}
if (physicalNetworkId != null && !physicalNetworkId.equals(associatedNetwork.getPhysicalNetworkId())) {
throw new InvalidParameterValueException("The network can only be created on the same physical network as the associated network");
} else if (physicalNetworkId == null) {
physicalNetworkId = associatedNetwork.getPhysicalNetworkId();
}
}
if (physicalNetworkId == null) {
// Determine the physical network by network offering tags
physicalNetworkId = _ntwkSvc.findPhysicalNetworkId(dcId, ntwkOff.getTags(), ntwkOff.getTrafficType());
}
if (physicalNetworkId == null) {
final List<? extends PhysicalNetwork> pNtwks = _ntwkModel.getPhysicalNtwksSupportingTrafficType(dcId, TrafficType.Guest);
if (pNtwks.isEmpty() || pNtwks.size() != 1) {
throw new InvalidParameterValueException("Physical network can't be determined; pass physical network id");
}
physicalNetworkId = pNtwks.get(0).getId();
}
return physicalNetworkId;
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_PRIVATE_GATEWAY_CREATE, eventDescription = "Applying VPC private gateway", async = true)
public PrivateGateway applyVpcPrivateGateway(final long gatewayId, final boolean destroyOnFailure) throws ConcurrentOperationException, ResourceUnavailableException {
@ -2005,6 +2087,17 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
throw new ConcurrentOperationException("Unable to lock gateway " + gatewayId);
}
final Account caller = CallContext.current().getCallingAccount();
if (!_accountMgr.isRootAdmin(caller.getId())) {
_accountMgr.checkAccess(caller, null, false, gatewayVO);
final NetworkVO networkVO = _ntwkDao.findById(gatewayVO.getNetworkId());
if (networkVO != null) {
_accountMgr.checkAccess(caller, null, false, networkVO);
if (_networkOfferingDao.findById(networkVO.getNetworkOfferingId()).isSpecifyVlan()) {
throw new InvalidParameterValueException("Unable to delete private gateway with specified vlan by non-ROOT accounts");
}
}
}
try {
Transaction.execute(new TransactionCallbackNoReturn() {
@Override

View File

@ -966,8 +966,10 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio
controlNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(controlNetworkOffering);
NetworkOfferingVO storageNetworkOffering = new NetworkOfferingVO(NetworkOffering.SystemStorageNetwork, TrafficType.Storage, true);
storageNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(storageNetworkOffering);
NetworkOfferingVO privateGatewayNetworkOffering = new NetworkOfferingVO(NetworkOffering.SystemPrivateGatewayNetworkOffering, GuestType.Isolated);
NetworkOfferingVO privateGatewayNetworkOffering = new NetworkOfferingVO(NetworkOffering.SystemPrivateGatewayNetworkOffering, GuestType.Isolated, true);
privateGatewayNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(privateGatewayNetworkOffering);
NetworkOfferingVO privateGatewayNetworkOfferingWithoutVlan = new NetworkOfferingVO(NetworkOffering.SystemPrivateGatewayNetworkOfferingWithoutVlan, GuestType.Isolated, false);
privateGatewayNetworkOfferingWithoutVlan = _networkOfferingDao.persistDefaultNetworkOffering(privateGatewayNetworkOfferingWithoutVlan);
//populate providers
final Map<Network.Service, Network.Provider> defaultSharedNetworkOfferingProviders = new HashMap<Network.Service, Network.Provider>();

View File

@ -44,6 +44,7 @@ import javax.inject.Inject;
import javax.naming.ConfigurationException;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.acl.SecurityChecker;
import org.apache.cloudstack.affinity.AffinityGroupProcessor;
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
import org.apache.cloudstack.annotation.AnnotationService;
@ -134,6 +135,7 @@ import org.apache.cloudstack.api.command.admin.network.DeleteNetworkServiceProvi
import org.apache.cloudstack.api.command.admin.network.DeletePhysicalNetworkCmd;
import org.apache.cloudstack.api.command.admin.network.DeleteStorageNetworkIpRangeCmd;
import org.apache.cloudstack.api.command.admin.network.ListDedicatedGuestVlanRangesCmd;
import org.apache.cloudstack.api.command.admin.network.ListGuestVlansCmd;
import org.apache.cloudstack.api.command.admin.network.ListNetworkDeviceCmd;
import org.apache.cloudstack.api.command.admin.network.ListNetworkIsolationMethodsCmd;
import org.apache.cloudstack.api.command.admin.network.ListNetworkServiceProvidersCmd;
@ -296,7 +298,7 @@ import org.apache.cloudstack.api.command.admin.volume.RecoverVolumeCmdByAdmin;
import org.apache.cloudstack.api.command.admin.volume.ResizeVolumeCmdByAdmin;
import org.apache.cloudstack.api.command.admin.volume.UpdateVolumeCmdByAdmin;
import org.apache.cloudstack.api.command.admin.volume.UploadVolumeCmdByAdmin;
import org.apache.cloudstack.api.command.admin.vpc.CreatePrivateGatewayCmd;
import org.apache.cloudstack.api.command.admin.vpc.CreatePrivateGatewayByAdminCmd;
import org.apache.cloudstack.api.command.admin.vpc.CreateVPCCmdByAdmin;
import org.apache.cloudstack.api.command.admin.vpc.CreateVPCOfferingCmd;
import org.apache.cloudstack.api.command.admin.vpc.DeletePrivateGatewayCmd;
@ -408,15 +410,19 @@ import org.apache.cloudstack.api.command.user.nat.ListIpForwardingRulesCmd;
import org.apache.cloudstack.api.command.user.network.CreateNetworkACLCmd;
import org.apache.cloudstack.api.command.user.network.CreateNetworkACLListCmd;
import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd;
import org.apache.cloudstack.api.command.user.network.CreateNetworkPermissionsCmd;
import org.apache.cloudstack.api.command.user.network.DeleteNetworkACLCmd;
import org.apache.cloudstack.api.command.user.network.DeleteNetworkACLListCmd;
import org.apache.cloudstack.api.command.user.network.DeleteNetworkCmd;
import org.apache.cloudstack.api.command.user.network.ListNetworkACLListsCmd;
import org.apache.cloudstack.api.command.user.network.ListNetworkACLsCmd;
import org.apache.cloudstack.api.command.user.network.ListNetworkOfferingsCmd;
import org.apache.cloudstack.api.command.user.network.ListNetworkPermissionsCmd;
import org.apache.cloudstack.api.command.user.network.ListNetworksCmd;
import org.apache.cloudstack.api.command.user.network.MoveNetworkAclItemCmd;
import org.apache.cloudstack.api.command.user.network.RemoveNetworkPermissionsCmd;
import org.apache.cloudstack.api.command.user.network.ReplaceNetworkACLListCmd;
import org.apache.cloudstack.api.command.user.network.ResetNetworkPermissionsCmd;
import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd;
import org.apache.cloudstack.api.command.user.network.UpdateNetworkACLItemCmd;
import org.apache.cloudstack.api.command.user.network.UpdateNetworkACLListCmd;
@ -525,6 +531,7 @@ import org.apache.cloudstack.api.command.user.volume.RemoveResourceDetailCmd;
import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.UpdateVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.UploadVolumeCmd;
import org.apache.cloudstack.api.command.user.vpc.CreatePrivateGatewayCmd;
import org.apache.cloudstack.api.command.user.vpc.CreateStaticRouteCmd;
import org.apache.cloudstack.api.command.user.vpc.CreateVPCCmd;
import org.apache.cloudstack.api.command.user.vpc.DeleteStaticRouteCmd;
@ -2201,7 +2208,13 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
if (networkMap == null) {
return new Pair<>(addrs, 0);
}
_accountMgr.checkAccess(caller, null, false, _accountDao.findById(networkMap.getAccountId()));
try {
_accountMgr.checkAccess(caller, null, false, _accountDao.findById(networkMap.getAccountId()));
} catch (PermissionDeniedException ex) {
s_logger.info("Account " + caller + " do not have permission to access account of network " + network);
_accountMgr.checkAccess(caller, SecurityChecker.AccessType.UseEntry, false, network);
isAllocated = Boolean.TRUE;
}
} else { // Domain level
NetworkDomainVO networkMap = _networkDomainDao.getDomainNetworkMapByNetworkId(network.getId());
if (networkMap == null) {
@ -3296,6 +3309,10 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
cmdList.add(ListNetworksCmd.class);
cmdList.add(RestartNetworkCmd.class);
cmdList.add(UpdateNetworkCmd.class);
cmdList.add(CreateNetworkPermissionsCmd.class);
cmdList.add(ListNetworkPermissionsCmd.class);
cmdList.add(RemoveNetworkPermissionsCmd.class);
cmdList.add(ResetNetworkPermissionsCmd.class);
cmdList.add(ListDiskOfferingsCmd.class);
cmdList.add(ListServiceOfferingsCmd.class);
cmdList.add(ActivateProjectCmd.class);
@ -3537,6 +3554,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
cmdList.add(CreateVPCCmdByAdmin.class);
cmdList.add(ListVPCsCmdByAdmin.class);
cmdList.add(UpdateVPCCmdByAdmin.class);
cmdList.add(CreatePrivateGatewayByAdminCmd.class);
cmdList.add(UpdateLBStickinessPolicyCmd.class);
cmdList.add(UpdateLBHealthCheckPolicyCmd.class);
cmdList.add(GetUploadParamsForTemplateCmd.class);
@ -3559,6 +3577,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
cmdList.add(UploadResourceIconCmd.class);
cmdList.add(DeleteResourceIconCmd.class);
cmdList.add(ListResourceIconCmd.class);
cmdList.add(ListGuestVlansCmd.class);
// Out-of-band management APIs for admins
cmdList.add(EnableOutOfBandManagementForHostCmd.class);

View File

@ -21,6 +21,7 @@ import java.net.URLEncoder;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
@ -106,6 +107,7 @@ import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.IpAddress;
import com.cloud.network.IpAddressManager;
import com.cloud.network.Network;
import com.cloud.network.NetworkModel;
import com.cloud.network.VpnUserVO;
import com.cloud.network.as.AutoScaleManager;
import com.cloud.network.dao.AccountGuestVlanMapDao;
@ -117,6 +119,7 @@ import com.cloud.network.dao.NetworkVO;
import com.cloud.network.dao.RemoteAccessVpnDao;
import com.cloud.network.dao.RemoteAccessVpnVO;
import com.cloud.network.dao.VpnUserDao;
import com.cloud.network.router.VirtualRouter;
import com.cloud.network.security.SecurityGroupManager;
import com.cloud.network.security.dao.SecurityGroupDao;
import com.cloud.network.vpc.Vpc;
@ -255,6 +258,8 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
@Inject
private VpcManager _vpcMgr;
@Inject
private NetworkModel _networkModel;
@Inject
private Site2SiteVpnManager _vpnMgr;
@Inject
private AutoScaleManager _autoscaleMgr;
@ -602,8 +607,9 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
Account account = ApiDBUtils.findAccountById(entity.getAccountId());
domainId = account != null ? account.getDomainId() : -1;
}
if (entity.getAccountId() != -1 && domainId != -1 && !(entity instanceof VirtualMachineTemplate) && !(entity instanceof Network && accessType != null && accessType == AccessType.UseEntry)
&& !(entity instanceof AffinityGroup)) {
if (entity.getAccountId() != -1 && domainId != -1 && !(entity instanceof VirtualMachineTemplate)
&& !(entity instanceof Network && accessType != null && (accessType == AccessType.UseEntry || accessType == AccessType.OperateEntry))
&& !(entity instanceof AffinityGroup) && !(entity instanceof VirtualRouter)) {
List<ControlledEntity> toBeChecked = domains.get(entity.getDomainId());
// for templates, we don't have to do cross domains check
if (toBeChecked == null) {
@ -886,7 +892,19 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
s_logger.debug("Deleting networks for account " + account.getId());
List<NetworkVO> networks = _networkDao.listByOwner(accountId);
if (networks != null) {
Collections.sort(networks, new Comparator<NetworkVO>() {
@Override
public int compare(NetworkVO network1, NetworkVO network2) {
if (network1.getGuestType() != network2.getGuestType() && Network.GuestType.Isolated.equals(network2.getGuestType())) {
return -1;
};
return 1;
}
});
for (NetworkVO network : networks) {
if (_networkModel.isPrivateGateway(network.getId())) {
continue;
}
ReservationContext context = new ReservationContextImpl(null, null, getActiveUser(callerUserId), caller);

View File

@ -1466,9 +1466,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
throw new InvalidParameterValueException(nic + " is not a nic on " + vmInstance);
}
// Perform account permission check on network
_accountMgr.checkAccess(caller, AccessType.UseEntry, false, network);
// don't delete default NIC on a user VM
if (nic.isDefaultNic() && vmInstance.getType() == VirtualMachine.Type.User) {
throw new InvalidParameterValueException("Unable to remove nic from " + vmInstance + " in " + network + ", nic is default.");
@ -4000,13 +3997,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
}
}
//relax the check if the caller is admin account
if (caller.getType() != Account.Type.ADMIN) {
if (!(network.getGuestType() == Network.GuestType.Shared && network.getAclType() == ACLType.Domain)
&& !(network.getAclType() == ACLType.Account && network.getAccountId() == accountId)) {
throw new InvalidParameterValueException("only shared network or isolated network with the same account_id can be added to vm");
}
}
_accountMgr.checkAccess(owner, AccessType.UseEntry, false, network);
IpAddresses requestedIpPair = null;
if (requestedIps != null && !requestedIps.isEmpty()) {

View File

@ -30,6 +30,7 @@ import java.util.List;
import java.util.UUID;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.log4j.Logger;
import org.junit.Before;
@ -58,6 +59,8 @@ import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.User;
import com.cloud.user.UserVO;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.TransactionLegacy;
import com.cloud.utils.exception.CloudRuntimeException;
@ -101,6 +104,9 @@ public class CreatePrivateNetworkTest {
Account account = new AccountVO("testaccount", 1, "networkdomain", Account.Type.NORMAL, UUID.randomUUID().toString());
when(networkService._accountMgr.getAccount(anyLong())).thenReturn(account);
UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN);
CallContext.register(user, account);
NetworkOfferingVO ntwkOff =
new NetworkOfferingVO("offer", "fakeOffer", TrafficType.Guest, true, true, null, null, false, null, null, GuestType.Isolated, false, false, false, false,
false, false, false, false, false, false, false, false, false, false, false, false);
@ -139,21 +145,21 @@ public class CreatePrivateNetworkTest {
/* Network nw; */
try {
/* nw = */
networkService.createPrivateNetwork("bla", "fake", 1L, "vlan:1", "10.1.1.2", null, "10.1.1.1", "255.255.255.0", 1L, 1L, true, 1L, false);
networkService.createPrivateNetwork("bla", "fake", 1L, "vlan:1", "10.1.1.2", null, "10.1.1.1", "255.255.255.0", 1L, 1L, true, 1L, false, null);
/* nw = */
networkService.createPrivateNetwork("bla", "fake", 1L, "lswitch:3", "10.1.1.2", null, "10.1.1.1", "255.255.255.0", 1L, 1L, false, 1L, false);
networkService.createPrivateNetwork("bla", "fake", 1L, "lswitch:3", "10.1.1.2", null, "10.1.1.1", "255.255.255.0", 1L, 1L, false, 1L, false, null);
boolean invalid = false;
boolean unsupported = false;
try {
/* nw = */
networkService.createPrivateNetwork("bla", "fake", 1, "bla:2", "10.1.1.2", null, "10.1.1.1", "255.255.255.0", 1, 1L, true, 1L, false);
networkService.createPrivateNetwork("bla", "fake", 1, "bla:2", "10.1.1.2", null, "10.1.1.1", "255.255.255.0", 1, 1L, true, 1L, false, null);
} catch (CloudRuntimeException e) {
Assert.assertEquals("unexpected parameter exception", "string 'bla:2' has an unknown BroadcastDomainType.", e.getMessage());
invalid = true;
}
try {
/* nw = */
networkService.createPrivateNetwork("bla", "fake", 1, "mido://4", "10.1.1.2", null, "10.1.1.1", "255.255.255.0", 1, 1L, false, 1L, false);
networkService.createPrivateNetwork("bla", "fake", 1, "mido://4", "10.1.1.2", null, "10.1.1.1", "255.255.255.0", 1, 1L, false, 1L, false, null);
} catch (InvalidParameterValueException e) {
Assert.assertEquals("unexpected parameter exception", "unsupported type of broadcastUri specified: mido://4", e.getMessage());
unsupported = true;

View File

@ -94,7 +94,7 @@ public class DedicateGuestVlanRangesTest {
networkService._accountDao = _accountDao;
networkService._projectMgr = _projectMgr;
networkService._physicalNetworkDao = _physicalNetworkDao;
networkService._datacneterVnet = _dataCenterVnetDao;
networkService._dcVnetDao = _dataCenterVnetDao;
networkService._accountGuestVlanMapDao = _accountGuestVlanMapDao;
Account account = new AccountVO("testaccount", 1, "networkdomain", Account.Type.NORMAL, UUID.randomUUID().toString());
@ -195,21 +195,21 @@ public class DedicateGuestVlanRangesTest {
when(networkService._physicalNetworkDao.findById(anyLong())).thenReturn(physicalNetwork);
when(networkService._datacneterVnet.listAllocatedVnetsInRange(anyLong(), anyLong(), anyInt(), anyInt())).thenReturn(null);
when(networkService._dcVnetDao.listAllocatedVnetsInRange(anyLong(), anyLong(), anyInt(), anyInt())).thenReturn(null);
when(networkService._accountGuestVlanMapDao.listAccountGuestVlanMapsByPhysicalNetwork(anyLong())).thenReturn(null);
when(networkService._accountGuestVlanMapDao.persist(any(AccountGuestVlanMapVO.class))).thenReturn(accountGuestVlanMapVO);
when(networkService._datacneterVnet.update(anyLong(), any(DataCenterVnetVO.class))).thenReturn(true);
when(networkService._dcVnetDao.update(anyLong(), any(DataCenterVnetVO.class))).thenReturn(true);
List<DataCenterVnetVO> dataCenterVnetList = new ArrayList<DataCenterVnetVO>();
DataCenterVnetVO dataCenterVnetVO = new DataCenterVnetVO("2-5", 1L, 1L);
dataCenterVnetList.add(dataCenterVnetVO);
when(networkService._datacneterVnet.findVnet(anyLong(), anyString())).thenReturn(dataCenterVnetList);
when(networkService._dcVnetDao.findVnet(anyLong(), anyString())).thenReturn(dataCenterVnetList);
try {
GuestVlan result = networkService.dedicateGuestVlanRange(dedicateGuestVlanRangesCmd);
GuestVlanRange result = networkService.dedicateGuestVlanRange(dedicateGuestVlanRangesCmd);
Assert.assertNotNull(result);
} catch (Exception e) {
s_logger.info("exception in testing runDedicateGuestVlanRangePostiveTest message: " + e.toString());
@ -275,7 +275,7 @@ public class DedicateGuestVlanRangesTest {
DataCenterVnetVO dataCenter = new DataCenterVnetVO("2-5", 1L, 1L);
dataCenter.setAccountId(1L);
dataCenterList.add(dataCenter);
when(networkService._datacneterVnet.listAllocatedVnetsInRange(anyLong(), anyLong(), anyInt(), anyInt())).thenReturn(dataCenterList);
when(networkService._dcVnetDao.listAllocatedVnetsInRange(anyLong(), anyLong(), anyInt(), anyInt())).thenReturn(dataCenterList);
try {
networkService.dedicateGuestVlanRange(dedicateGuestVlanRangesCmd);
@ -298,7 +298,7 @@ public class DedicateGuestVlanRangesTest {
when(networkService._physicalNetworkDao.findById(anyLong())).thenReturn(physicalNetwork);
when(networkService._datacneterVnet.listAllocatedVnetsInRange(anyLong(), anyLong(), anyInt(), anyInt())).thenReturn(null);
when(networkService._dcVnetDao.listAllocatedVnetsInRange(anyLong(), anyLong(), anyInt(), anyInt())).thenReturn(null);
List<AccountGuestVlanMapVO> guestVlanMaps = new ArrayList<AccountGuestVlanMapVO>();
AccountGuestVlanMapVO accountGuestVlanMap = new AccountGuestVlanMapVO(1L, 1L);
@ -327,7 +327,7 @@ public class DedicateGuestVlanRangesTest {
when(networkService._physicalNetworkDao.findById(anyLong())).thenReturn(physicalNetwork);
when(networkService._datacneterVnet.listAllocatedVnetsInRange(anyLong(), anyLong(), anyInt(), anyInt())).thenReturn(null);
when(networkService._dcVnetDao.listAllocatedVnetsInRange(anyLong(), anyLong(), anyInt(), anyInt())).thenReturn(null);
List<AccountGuestVlanMapVO> guestVlanMaps = new ArrayList<AccountGuestVlanMapVO>();
AccountGuestVlanMapVO accountGuestVlanMap = new AccountGuestVlanMapVO(2L, 1L);
@ -349,7 +349,7 @@ public class DedicateGuestVlanRangesTest {
AccountGuestVlanMapVO accountGuestVlanMap = new AccountGuestVlanMapVO(1L, 1L);
when(networkService._accountGuestVlanMapDao.findById(anyLong())).thenReturn(accountGuestVlanMap);
doNothing().when(networkService._datacneterVnet).releaseDedicatedGuestVlans(anyLong());
doNothing().when(networkService._dcVnetDao).releaseDedicatedGuestVlans(anyLong());
when(networkService._accountGuestVlanMapDao.remove(anyLong())).thenReturn(true);
try {

View File

@ -39,6 +39,7 @@ import com.cloud.network.dao.IPAddressVO;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.element.NetworkElement;
import com.cloud.network.element.UserDataServiceProvider;
import com.cloud.network.router.VirtualRouter;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.NetworkOffering.Detail;
import com.cloud.offerings.NetworkOfferingVO;
@ -524,6 +525,16 @@ public class MockNetworkModelImpl extends ManagerBase implements NetworkModel {
}
@Override
public void checkNetworkOperatePermissions(Account owner, Network network) {
}
@Override
public void checkRouterPermissions(Account owner, VirtualRouter router) {
}
/* (non-Javadoc)
* @see com.cloud.network.NetworkModel#getDefaultManagementTrafficLabel(long, com.cloud.hypervisor.Hypervisor.HypervisorType)
*/

View File

@ -49,7 +49,7 @@ public class UpdatePhysicalNetworkTest {
NetworkServiceImpl networkService = new NetworkServiceImpl();
networkService._dcDao = _datacenterDao;
networkService._physicalNetworkDao = _physicalNetworkDao;
networkService._datacneterVnet = _datacenterVnetDao;
networkService._dcVnetDao = _datacenterVnetDao;
return networkService;
}

View File

@ -17,16 +17,18 @@
package com.cloud.network.lb;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.network.Network;
import com.cloud.network.NetworkModelImpl;
import com.cloud.network.dao.LoadBalancerDao;
import com.cloud.network.dao.LoadBalancerVMMapDao;
import com.cloud.network.dao.LoadBalancerVMMapVO;
import com.cloud.network.dao.LoadBalancerVO;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.RulesManagerImpl;
import com.cloud.user.Account;
@ -41,6 +43,7 @@ import com.cloud.vm.NicVO;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.dao.NicSecondaryIpDao;
import com.cloud.vm.dao.UserVmDao;
import org.apache.cloudstack.acl.SecurityChecker;
import org.apache.cloudstack.api.ResponseGenerator;
import org.apache.cloudstack.api.command.user.loadbalancer.AssignToLoadBalancerRuleCmd;
import org.apache.cloudstack.api.response.SuccessResponse;
@ -54,8 +57,6 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.Spy;
import javax.inject.Inject;
import java.util.UUID;
import java.util.HashMap;
import java.util.Map;
@ -65,31 +66,17 @@ import java.util.ArrayList;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.when;
public class AssignLoadBalancerTest {
@Inject
AccountManager _accountMgr;
@Inject
AccountManager _acctMgr;
@Inject
AccountDao _accountDao;
@Inject
DomainDao _domainDao;
@Mock
List<LoadBalancerVMMapVO> _lbvmMapList;
@Mock
List<Nic> nic;
@Mock
UserVmDao userDao;
@Spy
RulesManagerImpl _rulesMgr = new RulesManagerImpl() {
@Override
@ -169,20 +156,31 @@ public class AssignLoadBalancerTest {
List<Long> vmIds = new ArrayList<Long>();
vmIds.add(2L);
LoadBalancerVO lbVO = new LoadBalancerVO("1", "L1", "Lbrule", 1, 22, 22, "rb", 204, 0, 0, "tcp");
UserVmVO vm = new UserVmVO(2L, "test", "test", 101L, Hypervisor.HypervisorType.Any, 21L, false, false, domainId, 200L, 1, 5L, "", "test");
LoadBalancerDao lbDao = Mockito.mock(LoadBalancerDao.class);
LoadBalancerVMMapDao lb2VmMapDao = Mockito.mock(LoadBalancerVMMapDao.class);
UserVmDao userVmDao = Mockito.mock(UserVmDao.class);
AccountDao accountDao = Mockito.mock(AccountDao.class);
NetworkDao networkDao = Mockito.mock(NetworkDao.class);
AccountManager accountMgr = Mockito.mock(AccountManager.class);
_lbMgr._lbDao = lbDao;
_lbMgr._lb2VmMapDao = lb2VmMapDao;
_lbMgr._vmDao = userVmDao;
_lbMgr._accountDao = accountDao;
_lbMgr._accountMgr = accountMgr;
_lbMgr._networkDao = networkDao;
_lbvmMapList = new ArrayList<>();
_lbMgr._rulesMgr = _rulesMgr;
_lbMgr._networkModel = _networkModel;
when(lbDao.findById(anyLong())).thenReturn(Mockito.mock(LoadBalancerVO.class));
when(userVmDao.findById(anyLong())).thenReturn(Mockito.mock(UserVmVO.class));
when(userVmDao.findById(anyLong())).thenReturn(vm);
when(lb2VmMapDao.listByLoadBalancerId(anyLong(), anyBoolean())).thenReturn(_lbvmMapList);
when(accountDao.findById(anyLong())).thenReturn(Mockito.mock(AccountVO.class));
Mockito.doNothing().when(accountMgr).checkAccess(any(Account.class), any(SecurityChecker.AccessType.class), any(Boolean.class), any(Network.class));
_lbMgr.assignToLoadBalancer(1L, null, vmIdIpMap);
}
@ -202,22 +200,29 @@ public class AssignLoadBalancerTest {
vmIds.add(2L);
LoadBalancerVO lbVO = new LoadBalancerVO("1", "L1", "Lbrule", 1, 22, 22, "rb", 204, 0, 0, "tcp");
UserVmVO vm = new UserVmVO(2L, "test", "test", 101L, Hypervisor.HypervisorType.Any, 21L, false, false, domainId, 200L, 1, 5L, "", "test");
LoadBalancerDao lbDao = Mockito.mock(LoadBalancerDao.class);
LoadBalancerVMMapDao lb2VmMapDao = Mockito.mock(LoadBalancerVMMapDao.class);
UserVmDao userVmDao = Mockito.mock(UserVmDao.class);
AccountDao accountDao = Mockito.mock(AccountDao.class);
NetworkDao networkDao = Mockito.mock(NetworkDao.class);
AccountManager accountMgr = Mockito.mock(AccountManager.class);
NicSecondaryIpDao nicSecIpDao = Mockito.mock(NicSecondaryIpDao.class);
_lbMgr._lbDao = lbDao;
_lbMgr._lb2VmMapDao = lb2VmMapDao;
_lbMgr._vmDao = userVmDao;
_lbMgr._accountDao = accountDao;
_lbMgr._accountMgr = accountMgr;
_lbMgr._networkDao = networkDao;
_lbMgr._nicSecondaryIpDao = nicSecIpDao;
_lbvmMapList = new ArrayList<>();
_lbMgr._rulesMgr = _rulesMgr;
_lbMgr._networkModel = _networkModel;
when(lbDao.findById(anyLong())).thenReturn(lbVO);
when(userVmDao.findById(anyLong())).thenReturn(Mockito.mock(UserVmVO.class));
when(userVmDao.findById(anyLong())).thenReturn(vm);
when(lb2VmMapDao.listByLoadBalancerId(anyLong(), anyBoolean())).thenReturn(_lbvmMapList);
when (nicSecIpDao.findByIp4AddressAndNicId(anyString(), anyLong())).thenReturn(null);
@ -240,16 +245,23 @@ public class AssignLoadBalancerTest {
vmIds.add(2L);
LoadBalancerVO lbVO = new LoadBalancerVO("1", "L1", "Lbrule", 1, 22, 22, "rb", 204, 0, 0, "tcp");
UserVmVO vm = new UserVmVO(2L, "test", "test", 101L, Hypervisor.HypervisorType.Any, 21L, false, false, domainId, 200L, 1, 5L, "", "test");
LoadBalancerDao lbDao = Mockito.mock(LoadBalancerDao.class);
LoadBalancerVMMapDao lb2VmMapDao = Mockito.mock(LoadBalancerVMMapDao.class);
UserVmDao userVmDao = Mockito.mock(UserVmDao.class);
AccountDao accountDao = Mockito.mock(AccountDao.class);
AccountManager accountMgr = Mockito.mock(AccountManager.class);
NetworkDao networkDao = Mockito.mock(NetworkDao.class);
NicSecondaryIpDao nicSecIpDao = Mockito.mock(NicSecondaryIpDao.class);
LoadBalancerVMMapVO lbVmMapVO = new LoadBalancerVMMapVO(1L, 1L, "10.1.1.175", false);
_lbMgr._lbDao = lbDao;
_lbMgr._lb2VmMapDao = lb2VmMapDao;
_lbMgr._vmDao = userVmDao;
_lbMgr._accountDao = accountDao;
_lbMgr._accountMgr = accountMgr;
_lbMgr._networkDao = networkDao;
_lbMgr._nicSecondaryIpDao = nicSecIpDao;
_lbvmMapList = new ArrayList<>();
_lbvmMapList.add(lbVmMapVO);
@ -257,7 +269,7 @@ public class AssignLoadBalancerTest {
_lbMgr._networkModel = _networkModel;
when(lbDao.findById(anyLong())).thenReturn(lbVO);
when(userVmDao.findById(anyLong())).thenReturn(Mockito.mock(UserVmVO.class));
when(userVmDao.findById(anyLong())).thenReturn(vm);
when(lb2VmMapDao.listByLoadBalancerId(anyLong(), anyBoolean())).thenReturn(_lbvmMapList);
when (nicSecIpDao.findByIp4AddressAndNicId(anyString(), anyLong())).thenReturn(null);

View File

@ -28,9 +28,14 @@ import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.api.command.admin.address.ReleasePodIpCmdByAdmin;
import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd;
import org.apache.cloudstack.api.command.admin.network.ListDedicatedGuestVlanRangesCmd;
import org.apache.cloudstack.api.command.admin.network.ListGuestVlansCmd;
import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd;
import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd;
import org.apache.cloudstack.api.command.user.network.CreateNetworkPermissionsCmd;
import org.apache.cloudstack.api.command.user.network.ListNetworkPermissionsCmd;
import org.apache.cloudstack.api.command.user.network.ListNetworksCmd;
import org.apache.cloudstack.api.command.user.network.RemoveNetworkPermissionsCmd;
import org.apache.cloudstack.api.command.user.network.ResetNetworkPermissionsCmd;
import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd;
import org.apache.cloudstack.api.command.user.network.UpdateNetworkCmd;
import org.apache.cloudstack.api.command.user.vm.ListNicsCmd;
@ -49,11 +54,13 @@ import com.cloud.exception.InsufficientVirtualNetworkCapacityException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.GuestVlan;
import com.cloud.network.GuestVlanRange;
import com.cloud.network.IpAddress;
import com.cloud.network.Network;
import com.cloud.network.Network.IpAddresses;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.NetworkPermission;
import com.cloud.network.NetworkProfile;
import com.cloud.network.NetworkService;
import com.cloud.network.Networks.TrafficType;
@ -318,13 +325,13 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkOrches
}
@Override
public GuestVlan dedicateGuestVlanRange(DedicateGuestVlanRangeCmd cmd) {
public GuestVlanRange dedicateGuestVlanRange(DedicateGuestVlanRangeCmd cmd) {
// TODO Auto-generated method stub
return null;
}
@Override
public Pair<List<? extends GuestVlan>, Integer> listDedicatedGuestVlanRanges(ListDedicatedGuestVlanRangesCmd cmd) {
public Pair<List<? extends GuestVlanRange>, Integer> listDedicatedGuestVlanRanges(ListDedicatedGuestVlanRangesCmd cmd) {
// TODO Auto-generated method stub
return null;
}
@ -516,7 +523,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkOrches
*/
@Override
public Network createPrivateNetwork(String networkName, String displayText, long physicalNetworkId, String vlan, String startIp, String endIP, String gateway,
String netmask, long networkOwnerId, Long vpcId, Boolean sourceNat, Long networkOfferingId, Boolean bypassVlanOverlapCheck) throws ResourceAllocationException, ConcurrentOperationException,
String netmask, long networkOwnerId, Long vpcId, Boolean sourceNat, Long networkOfferingId, Boolean bypassVlanOverlapCheck, Long associatedNetworkId) throws ResourceAllocationException, ConcurrentOperationException,
InsufficientCapacityException {
// TODO Auto-generated method stub
return null;
@ -973,6 +980,11 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkOrches
}
@Override
public boolean isSharedNetworkWithoutSpecifyVlan(NetworkOffering offering) {
return false;
}
@Override
public IpAddress updateIP(Long id, String customId, Boolean displayIp) {
// TODO Auto-generated method stub
@ -1007,4 +1019,29 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkOrches
@Override
public void unmanageNics(VirtualMachineProfile vm) {
}
@Override
public Pair<List<? extends GuestVlan>, Integer> listGuestVlans(ListGuestVlansCmd cmd) {
return null;
}
@Override
public List<? extends NetworkPermission> listNetworkPermissions(ListNetworkPermissionsCmd listNetworkPermissionsCmd) {
return null;
}
@Override
public boolean createNetworkPermissions(CreateNetworkPermissionsCmd createNetworkPermissionsCmd) {
return false;
}
@Override
public boolean removeNetworkPermissions(RemoveNetworkPermissionsCmd removeNetworkPermissionsCmd) {
return false;
}
@Override
public boolean resetNetworkPermissions(ResetNetworkPermissionsCmd resetNetworkPermissionsCmd) {
return false;
}
}

View File

@ -46,6 +46,7 @@ import com.cloud.network.dao.IPAddressVO;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.element.NetworkElement;
import com.cloud.network.element.UserDataServiceProvider;
import com.cloud.network.router.VirtualRouter;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.NetworkOffering.Detail;
import com.cloud.offerings.NetworkOfferingVO;
@ -541,6 +542,16 @@ public class MockNetworkModelImpl extends ManagerBase implements NetworkModel {
}
@Override
public void checkNetworkOperatePermissions(Account owner, Network network) {
}
@Override
public void checkRouterPermissions(Account owner, VirtualRouter router) {
}
/* (non-Javadoc)
* @see com.cloud.network.NetworkModel#getDefaultManagementTrafficLabel(long, com.cloud.hypervisor.Hypervisor.HypervisorType)
*/

View File

@ -136,12 +136,12 @@ public class CreateNetworkOfferingTest extends TestCase {
assertNotNull("Shared network offering with specifyVlan=true failed to create ", off);
}
@Test(expected=InvalidParameterValueException.class)
@Test
public void createSharedNtwkOffWithNoVlan() {
NetworkOfferingVO off =
configMgr.createNetworkOffering("shared", "shared", TrafficType.Guest, null, false, Availability.Optional, 200, null, false, Network.GuestType.Shared,
false, null, false, null, true, false, null, false, null, true, false, null, null, false);
assertNull("Shared network offering with specifyVlan=false was created", off);
assertNotNull("Shared network offering with specifyVlan=false was created", off);
}
@Test

View File

@ -39,7 +39,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.command.admin.vpc.CreatePrivateGatewayCmd;
import org.apache.cloudstack.api.command.user.vpc.CreatePrivateGatewayCmd;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.test.utils.SpringUtils;

View File

@ -0,0 +1,760 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
"""
Tests of network permissions
"""
import logging
from nose.plugins.attrib import attr
from marvin.cloudstackTestCase import cloudstackTestCase
from marvin.lib.base import (Account,
Configurations,
Domain,
Project,
ServiceOffering,
VirtualMachine,
Zone,
Network,
NetworkOffering,
NetworkPermission,
NIC,
PublicIPAddress,
LoadBalancerRule,
NATRule,
StaticNATRule,
SSHKeyPair)
from marvin.lib.common import (get_domain,
get_zone,
get_template)
NETWORK_FILTER_ACCOUNT = 'account'
NETWORK_FILTER_DOMAIN = 'domain'
NETWORK_FILTER_ACCOUNT_DOMAIN = 'accountdomain'
NETWORK_FILTER_SHARED = 'shared'
NETWORK_FILTER_ALL = 'all'
class TestNetworkPermissions(cloudstackTestCase):
"""
Test user-shared networks
"""
@classmethod
def setUpClass(cls):
cls.testClient = super(
TestNetworkPermissions,
cls).getClsTestClient()
cls.apiclient = cls.testClient.getApiClient()
cls.services = cls.testClient.getParsedTestDataConfig()
zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests())
cls.zone = Zone(zone.__dict__)
cls.template = get_template(cls.apiclient, cls.zone.id)
cls._cleanup = []
cls.logger = logging.getLogger("TestNetworkPermissions")
cls.stream_handler = logging.StreamHandler()
cls.logger.setLevel(logging.DEBUG)
cls.logger.addHandler(cls.stream_handler)
cls.domain = get_domain(cls.apiclient)
# Create small service offering
cls.service_offering = ServiceOffering.create(
cls.apiclient,
cls.services["service_offerings"]["small"]
)
cls._cleanup.append(cls.service_offering)
# Create network offering for isolated networks
cls.network_offering_isolated = NetworkOffering.create(
cls.apiclient,
cls.services["isolated_network_offering"]
)
cls.network_offering_isolated.update(cls.apiclient, state='Enabled')
cls._cleanup.append(cls.network_offering_isolated)
# Create sub-domain
cls.sub_domain = Domain.create(
cls.apiclient,
cls.services["acl"]["domain1"]
)
cls._cleanup.append(cls.sub_domain)
# Create domain admin and normal user
cls.domain_admin = Account.create(
cls.apiclient,
cls.services["acl"]["accountD1A"],
admin=True,
domainid=cls.sub_domain.id
)
cls._cleanup.append(cls.domain_admin)
cls.network_owner = Account.create(
cls.apiclient,
cls.services["acl"]["accountD11A"],
domainid=cls.sub_domain.id
)
cls._cleanup.append(cls.network_owner)
cls.other_user = Account.create(
cls.apiclient,
cls.services["acl"]["accountD11B"],
domainid=cls.sub_domain.id
)
cls._cleanup.append(cls.other_user)
# Create project
cls.project = Project.create(
cls.apiclient,
cls.services["project"],
account=cls.domain_admin.name,
domainid=cls.domain_admin.domainid
)
cls._cleanup.append(cls.project)
# Create api clients for domain admin and normal user
cls.domainadmin_user = cls.domain_admin.user[0]
cls.domainadmin_apiclient = cls.testClient.getUserApiClient(
cls.domainadmin_user.username, cls.sub_domain.name
)
cls.networkowner_user = cls.network_owner.user[0]
cls.user_apiclient = cls.testClient.getUserApiClient(
cls.networkowner_user.username, cls.sub_domain.name
)
cls.otheruser_user = cls.other_user.user[0]
cls.otheruser_apiclient = cls.testClient.getUserApiClient(
cls.otheruser_user.username, cls.sub_domain.name
)
# Create networks for domain admin, normal user and project
cls.services["network"]["name"] = "Test Network Isolated - Project"
cls.project_network = Network.create(
cls.apiclient,
cls.services["network"],
networkofferingid=cls.network_offering_isolated.id,
domainid=cls.sub_domain.id,
projectid=cls.project.id,
zoneid=cls.zone.id
)
cls._cleanup.append(cls.project_network)
cls.services["network"]["name"] = "Test Network Isolated - Domain admin"
cls.domainadmin_network = Network.create(
cls.apiclient,
cls.services["network"],
networkofferingid=cls.network_offering_isolated.id,
domainid=cls.sub_domain.id,
accountid=cls.domain_admin.name,
zoneid=cls.zone.id
)
cls._cleanup.append(cls.domainadmin_network)
cls.services["network"]["name"] = "Test Network Isolated - Normal user"
cls.user_network = Network.create(
cls.apiclient,
cls.services["network"],
networkofferingid=cls.network_offering_isolated.id,
domainid=cls.sub_domain.id,
accountid=cls.network_owner.name,
zoneid=cls.zone.id
)
cls._cleanup.append(cls.user_network)
@classmethod
def tearDownClass(cls):
super(TestNetworkPermissions, cls).tearDownClass()
def setUp(self):
self.cleanup = []
self.virtual_machine = None
def tearDown(self):
super(TestNetworkPermissions, self).tearDown()
def list_network(self, apiclient, account, network, project, network_filter=None, expected=True):
# List networks by apiclient, account, network, project and network network_filter
# If account is specified, list the networks which can be used by the domain (canusefordeploy=true,listall=false)
# otherwise canusefordeploy is None and listall is True.
domain_id = None
account_name = None
project_id = None
canusefordeploy = None
list_all = True
if account:
domain_id = account.domainid
account_name = account.name
canusefordeploy = True
list_all = False
if project:
project_id = project.id
networks = None
try:
networks = Network.list(
apiclient,
canusefordeploy=canusefordeploy,
listall=list_all,
networkfilter= network_filter,
domainid=domain_id,
account=account_name,
projectid=project_id,
id=network.id
)
if isinstance(networks, list) and len(networks) > 0:
if not expected:
self.fail("Found the network, but expected to fail")
elif expected:
self.fail("Failed to find the network, but expected to succeed")
except Exception as ex:
networks = None
if expected:
self.fail(f"Failed to list network, but expected to succeed : {ex}")
if networks and not expected:
self.fail("network is listed successfully, but expected to fail")
def list_network_by_filters(self, apiclient, account, network, project, expected_results=None):
# expected results in order: account/domain/accountdomain/shared/all
self.list_network(apiclient, account, network, project, NETWORK_FILTER_ACCOUNT, expected_results[0])
self.list_network(apiclient, account, network, project, NETWORK_FILTER_DOMAIN, expected_results[1])
self.list_network(apiclient, account, network, project, NETWORK_FILTER_ACCOUNT_DOMAIN, expected_results[2])
self.list_network(apiclient, account, network, project, NETWORK_FILTER_SHARED, expected_results[3])
self.list_network(apiclient, account, network, project, NETWORK_FILTER_ALL, expected_results[4])
def create_network_permission(self, apiclient, network, account, project, expected=True):
account_id = None
project_id = None
if account:
account_id = account.id
if project:
project_id = project.id
result = True
try:
NetworkPermission.create(
apiclient,
networkid=network.id,
accountids=account_id,
projectids=project_id
)
except Exception as ex:
result = False
if expected:
self.fail(f"Failed to create network permissions, but expected to succeed : {ex}")
if result and not expected:
self.fail("network permission is created successfully, but expected to fail")
def remove_network_permission(self, apiclient, network, account, project, expected=True):
account_id = None
project_id = None
if account:
account_id = account.id
if project:
project_id = project.id
result = True
try:
NetworkPermission.remove(
apiclient,
networkid=network.id,
accountids=account_id,
projectids=project_id
)
except Exception as ex:
result = False
if expected:
self.fail(f"Failed to remove network permissions, but expected to succeed : {ex}")
if result and not expected:
self.fail("network permission is removed successfully, but expected to fail")
def reset_network_permission(self, apiclient, network, expected=True):
result = True
try:
NetworkPermission.reset(
apiclient,
networkid=network.id
)
except Exception as ex:
result = False
if expected:
self.fail(f"Failed to reset network permissions, but expected to succeed : {ex}")
if result and not expected:
self.fail("network permission is reset successfully, but expected to fail")
def exec_command(self, apiclient_str, command, expected=None):
result = True
try:
command = command.format(apiclient = apiclient_str)
exec(command)
except Exception as ex:
result = False
if expected:
self.fail(f"Failed to execute command '{command}' with exception : {ex}")
if result and expected is False:
self.fail(f"command {command} is executed successfully, but expected to fail")
if expected is None:
# if expected is None, display the command and result
self.logger.info(f"Result of command '{command}' : {result}")
return result
@attr(tags=["advanced"], required_hardware="false")
def test_01_network_permission_on_project_network(self):
""" Testing network permissions on project network """
self.create_network_permission(self.apiclient, self.project_network, self.domain_admin, None, expected=False)
self.create_network_permission(self.domainadmin_apiclient, self.project_network, self.domain_admin, None, expected=False)
self.create_network_permission(self.user_apiclient, self.project_network, self.network_owner, None, expected=False)
@attr(tags=["advanced"], required_hardware="false")
def test_02_network_permission_on_user_network(self):
""" Testing network permissions on user network """
# List user network by domain admin
self.list_network_by_filters(self.domainadmin_apiclient, None, self.user_network, None, [True, False, True, False, True])
self.list_network_by_filters(self.domainadmin_apiclient, self.domain_admin, self.user_network, None, [False, False, False, False, False])
# Create network permissions
self.create_network_permission(self.apiclient, self.user_network, self.domain_admin, None, expected=True)
self.create_network_permission(self.domainadmin_apiclient, self.user_network, self.domain_admin, None, expected=True)
self.create_network_permission(self.user_apiclient, self.user_network, self.network_owner, None, expected=True)
self.create_network_permission(self.user_apiclient, self.user_network, self.other_user, None, expected=True)
self.create_network_permission(self.user_apiclient, self.user_network, None, self.project, expected=False)
self.create_network_permission(self.domainadmin_apiclient, self.user_network, None, self.project, expected=True)
self.create_network_permission(self.otheruser_apiclient, self.user_network, self.network_owner, None, expected=False)
# List domain admin network by domain admin
self.list_network_by_filters(self.domainadmin_apiclient, None, self.domainadmin_network, None, [True, False, True, False, True])
self.list_network_by_filters(self.domainadmin_apiclient, self.domain_admin, self.domainadmin_network, None, [True, False, True, False, True])
# List user network by domain admin
self.list_network_by_filters(self.domainadmin_apiclient, None, self.user_network, None, [True, False, True, True, True])
self.list_network_by_filters(self.domainadmin_apiclient, self.domain_admin, self.user_network, None, [False, False, False, True, True])
# List user network by user
self.list_network_by_filters(self.user_apiclient, None, self.user_network, None, [True, False, True, False, True])
self.list_network_by_filters(self.user_apiclient, self.network_owner, self.user_network, None, [True, False, True, False, True])
# List user network by other user
self.list_network_by_filters(self.otheruser_apiclient, None, self.user_network, None, [False, False, False, True, True])
self.list_network_by_filters(self.otheruser_apiclient, self.network_owner, self.user_network, None, [False, False, False, False, False])
# Remove network permissions
self.remove_network_permission(self.domainadmin_apiclient, self.user_network, self.domain_admin, None, expected=True)
# List user network by domain admin
self.list_network_by_filters(self.domainadmin_apiclient, None, self.user_network, None, [True, False, True, True, True])
self.list_network_by_filters(self.domainadmin_apiclient, self.domain_admin, self.user_network, None, [False, False, False, False, False])
# Reset network permissions
self.reset_network_permission(self.domainadmin_apiclient, self.user_network, expected=True)
# List user network by domain admin
self.list_network_by_filters(self.domainadmin_apiclient, None, self.user_network, None, [True, False, True, False, True])
self.list_network_by_filters(self.domainadmin_apiclient, self.domain_admin, self.user_network, None, [False, False, False, False, False])
@attr(tags=["advanced"], required_hardware="false")
def test_03_network_operations_on_created_vm_of_otheruser(self):
""" Testing network operations on a create vm owned by other user"""
# 1. Create an Isolated network by other user
self.services["network"]["name"] = "Test Network Isolated - Other user"
otheruser_network = Network.create(
self.otheruser_apiclient,
self.services["network"],
networkofferingid=self.network_offering_isolated.id,
zoneid=self.zone.id
)
self.cleanup.append(otheruser_network)
# 2. Deploy vm1 on other user's network
self.virtual_machine = VirtualMachine.create(
self.otheruser_apiclient,
self.services["virtual_machine"],
templateid=self.template.id,
serviceofferingid=self.service_offering.id,
networkids=otheruser_network.id,
zoneid=self.zone.id
)
# 3. Add user network to vm1, should fail by vm owner and network owner
command = """self.virtual_machine.add_nic({apiclient}, self.user_network.id)"""
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.otheruser_apiclient", command, expected=False)
# 4. Create network permission for other user, should succeed by network owner
command = """self.create_network_permission({apiclient}, self.user_network, self.other_user, None, expected=True)"""
self.exec_command("self.otheruser_apiclient", command, expected=False)
self.exec_command("self.user_apiclient", command, expected=True)
# 5. Add user network to vm1, should succeed by vm owner
command = """self.virtual_machine.add_nic({apiclient}, self.user_network.id)"""
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.otheruser_apiclient", command, expected=True)
# 6. Stop vm1 with forced=true, should succeed by vm owner
command = """self.virtual_machine.stop({apiclient}, forced=True)"""
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.otheruser_apiclient", command, expected=True)
# Get id of the additional nic
list_vms = VirtualMachine.list(
self.otheruser_apiclient,
id = self.virtual_machine.id
)
self.assertEqual(
isinstance(list_vms, list),
True,
"Check if virtual machine is present"
)
self.assertEqual(
len(list_vms) > 0,
True,
"Check if virtual machine list is empty"
)
self.vm_default_nic_id = None
self.vm_new_nic_id = None
for vm_nic in list_vms[0].nic:
if vm_nic.networkid == self.user_network.id:
self.vm_new_nic_id = vm_nic.id
else:
self.vm_default_nic_id = vm_nic.id
# 6. Update vm1 nic IP, should succeed by vm owner
command = """NIC.updateIp({apiclient}, self.vm_new_nic_id)"""
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.otheruser_apiclient", command, expected=True)
# 7. Start vm1, should succeed by vm owner
command = """self.virtual_machine.start({apiclient})"""
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.otheruser_apiclient", command, expected=True)
# 8. Add secondary IP to nic, should succeed by vm owner
command = """self.secondaryip = NIC.addIp({apiclient}, self.vm_new_nic_id)"""
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.otheruser_apiclient", command, expected=True)
# 9 Remove secondary IP from nic, should succeed by vm owner
command = """NIC.removeIp({apiclient}, self.secondaryip.id)"""
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.otheruser_apiclient", command, expected=True)
# 10. Update default NIC, should succeed by vm owner
command = """self.virtual_machine.update_default_nic({apiclient}, self.vm_new_nic_id)"""
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.otheruser_apiclient", command, expected=True)
command = """self.virtual_machine.update_default_nic({apiclient}, self.vm_default_nic_id)"""
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.otheruser_apiclient", command, expected=True)
# 11. Stop vm1 with forced=true
command = """self.virtual_machine.stop({apiclient}, forced=True)"""
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.otheruser_apiclient", command, expected=True)
# 12. Remove nic from vm1, should succeed by vm owner
command = """self.virtual_machine.remove_nic({apiclient}, self.vm_new_nic_id)"""
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.otheruser_apiclient", command, expected=True)
# 13. Test operations by domain admin
command = """self.virtual_machine.add_nic({apiclient}, self.user_network.id)"""
self.exec_command("self.domainadmin_apiclient", command, expected=True)
list_vms = VirtualMachine.list(
self.otheruser_apiclient,
id = self.virtual_machine.id
)
self.vm_default_nic_id = None
self.vm_new_nic_id = None
for vm_nic in list_vms[0].nic:
if vm_nic.networkid == self.user_network.id:
self.vm_new_nic_id = vm_nic.id
else:
self.vm_default_nic_id = vm_nic.id
command = """NIC.updateIp({apiclient}, self.vm_new_nic_id)"""
self.exec_command("self.domainadmin_apiclient", command, expected=True)
command = """self.secondaryip = NIC.addIp({apiclient}, self.vm_new_nic_id)"""
self.exec_command("self.domainadmin_apiclient", command, expected=True)
command = """NIC.removeIp({apiclient}, self.secondaryip.id)"""
self.exec_command("self.domainadmin_apiclient", command, expected=True)
command = """self.virtual_machine.update_default_nic({apiclient}, self.vm_new_nic_id)"""
self.exec_command("self.domainadmin_apiclient", command, expected=True)
command = """self.virtual_machine.update_default_nic({apiclient}, self.vm_default_nic_id)"""
self.exec_command("self.domainadmin_apiclient", command, expected=True)
command = """self.virtual_machine.remove_nic({apiclient}, self.vm_new_nic_id)"""
self.exec_command("self.domainadmin_apiclient", command, expected=True)
# 14. Test operations by vm owner, when network permission is removed
command = """self.virtual_machine.add_nic({apiclient}, self.user_network.id)"""
self.exec_command("self.domainadmin_apiclient", command, expected=True)
# 15. Reset network permissions, should succeed by network owner
command = """self.reset_network_permission({apiclient}, self.user_network, expected=True)"""
self.exec_command("self.otheruser_apiclient", command, expected=False)
self.exec_command("self.user_apiclient", command, expected=True)
list_vms = VirtualMachine.list(
self.otheruser_apiclient,
id = self.virtual_machine.id
)
self.vm_default_nic_id = None
self.vm_new_nic_id = None
for vm_nic in list_vms[0].nic:
if vm_nic.networkid == self.user_network.id:
self.vm_new_nic_id = vm_nic.id
else:
self.vm_default_nic_id = vm_nic.id
command = """NIC.updateIp({apiclient}, self.vm_new_nic_id)"""
self.exec_command("self.otheruser_apiclient", command, expected=True)
command = """self.secondaryip = NIC.addIp({apiclient}, self.vm_new_nic_id)"""
if self.exec_command("self.otheruser_apiclient", command, expected=True):
command = """NIC.removeIp({apiclient}, self.secondaryip.id)"""
self.exec_command("self.otheruser_apiclient", command, expected=True)
command = """self.virtual_machine.update_default_nic({apiclient}, self.vm_new_nic_id)"""
if self.exec_command("self.otheruser_apiclient", command, expected=True):
command = """self.virtual_machine.update_default_nic({apiclient}, self.vm_default_nic_id)"""
self.exec_command("self.otheruser_apiclient", command, expected=True)
command = """self.virtual_machine.start({apiclient})"""
if self.exec_command("self.otheruser_apiclient", command, expected=True):
command = """self.virtual_machine.stop({apiclient}, forced=True)"""
self.exec_command("self.otheruser_apiclient", command, expected=True)
command = """self.virtual_machine.remove_nic({apiclient}, self.vm_new_nic_id)"""
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.otheruser_apiclient", command, expected=True)
#self.exec_command("self.domainadmin_apiclient", command, expected=True)
# 16. Destroy vm1, should succeed by root admin
self.virtual_machine.delete(self.apiclient, expunge=True)
@attr(tags=["advanced"], required_hardware="false")
def test_04_deploy_vm_for_other_user_and_test_vm_operations(self):
""" Deploy VM for other user and test VM operations by vm owner, network owner and domain admin"""
# 1. Create network permission for other user, by user
command = """self.create_network_permission({apiclient}, self.user_network, self.other_user, None, expected=True)"""
self.exec_command("self.otheruser_apiclient", command, expected=False)
self.exec_command("self.user_apiclient", command, expected=True)
# 2. Deploy vm2 on user network
command = """self.virtual_machine = VirtualMachine.create(
{apiclient},
self.services["virtual_machine"],
templateid=self.template.id,
serviceofferingid=self.service_offering.id,
networkids=self.user_network.id,
accountid=self.other_user.name,
domainid=self.other_user.domainid,
zoneid=self.zone.id
)"""
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.otheruser_apiclient", command, expected=True)
if not self.virtual_machine:
self.fail("Failed to find self.virtual_machine")
# 3. List vm2
list_vms = VirtualMachine.list(
self.user_apiclient,
id = self.virtual_machine.id
)
self.assertEqual(
isinstance(list_vms, list) and len(list_vms) > 0,
False,
"Check if virtual machine is not present"
)
list_vms = VirtualMachine.list(
self.otheruser_apiclient,
id = self.virtual_machine.id
)
self.assertEqual(
isinstance(list_vms, list) and len(list_vms) > 0,
True,
"Check if virtual machine is present"
)
# 4. Stop vm2 with forced=true
command = """self.virtual_machine.stop({apiclient}, forced=True)"""
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.otheruser_apiclient", command, expected=True)
# 5. Reset vm password
if self.template.passwordenabled:
command = """self.virtual_machine.resetPassword({apiclient})"""
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.otheruser_apiclient", command, expected=True)
# 6. Reset vm SSH key
self.keypair = SSHKeyPair.create(
self.otheruser_apiclient,
name=self.other_user.name + ".pem"
)
command = """self.virtual_machine.resetSshKey({apiclient}, keypair=self.keypair.name)"""
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.otheruser_apiclient", command, expected=True)
# 7. Start vm2
command = """self.virtual_machine.start({apiclient})"""
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.otheruser_apiclient", command, expected=True)
# 8. Acquire public IP, should succeed by domain admin and network owner
command = """self.public_ip = PublicIPAddress.create(
{apiclient},
zoneid=self.zone.id,
networkid=self.user_network.id
)"""
self.exec_command("self.otheruser_apiclient", command, expected=False)
self.exec_command("self.user_apiclient", command, expected=True)
#self.exec_command("self.domainadmin_apiclient", command, expected=True)
# 9. Enable static nat, should succeed by domain admin
command = """StaticNATRule.enable(
{apiclient},
ipaddressid=self.public_ip.ipaddress.id,
virtualmachineid=self.virtual_machine.id
)"""
self.exec_command("self.otheruser_apiclient", command, expected=False)
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.domainadmin_apiclient", command, expected=True)
# 10. Disable static nat, should succeed by domain admin and network owner
command = """StaticNATRule.disable(
{apiclient},
ipaddressid=self.public_ip.ipaddress.id
)"""
self.exec_command("self.otheruser_apiclient", command, expected=False)
self.exec_command("self.user_apiclient", command, expected=True)
#self.exec_command("self.domainadmin_apiclient", command, expected=True)
# 11. Create port forwarding rule, should succeed by domain admin
command = """self.port_forwarding_rule = NATRule.create(
{apiclient},
virtual_machine=self.virtual_machine,
services=self.services["natrule"],
ipaddressid=self.public_ip.ipaddress.id,
)"""
self.exec_command("self.otheruser_apiclient", command, expected=False)
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.domainadmin_apiclient", command, expected=True)
# 12. Delete port forwarding rule, should succeed by domain admin and network owner
command = """self.port_forwarding_rule.delete({apiclient})"""
self.exec_command("self.otheruser_apiclient", command, expected=False)
self.exec_command("self.user_apiclient", command, expected=True)
#self.exec_command("self.domainadmin_apiclient", command, expected=True)
# 13. Create load balancer rule, should succeed by domain admin and network owner
command = """self.load_balancer_rule = LoadBalancerRule.create(
{apiclient},
self.services["lbrule"],
ipaddressid=self.public_ip.ipaddress.id,
networkid=self.user_network.id,
)"""
self.exec_command("self.otheruser_apiclient", command, expected=False)
self.exec_command("self.user_apiclient", command, expected=True)
#self.exec_command("self.domainadmin_apiclient", command, expected=True)
# 14. Assign virtual machine to load balancing rule, should succeed by domain admin
command = """self.load_balancer_rule.assign({apiclient}, vms=[self.virtual_machine])"""
self.exec_command("self.otheruser_apiclient", command, expected=False)
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.domainadmin_apiclient", command, expected=True)
# 15. Remove virtual machine from load balancing rule, should succeed by domain admin and network owner
command = """self.load_balancer_rule.remove({apiclient}, vms=[self.virtual_machine])"""
self.exec_command("self.otheruser_apiclient", command, expected=False)
self.exec_command("self.user_apiclient", command, expected=True)
#self.exec_command("self.domainadmin_apiclient", command, expected=True)
# 16. Delete load balancing rule, should succeed by domain admin and network owner
command = """self.load_balancer_rule.delete({apiclient})"""
self.exec_command("self.otheruser_apiclient", command, expected=False)
self.exec_command("self.user_apiclient", command, expected=True)
#self.exec_command("self.domainadmin_apiclient", command, expected=True)
# 17. Release public IP, should succeed by domain admin and network owner
command = """self.public_ip.delete({apiclient})"""
self.exec_command("self.otheruser_apiclient", command, expected=False)
self.exec_command("self.user_apiclient", command, expected=True)
#self.exec_command("self.domainadmin_apiclient", command, expected=True)
# 18. Stop vm2 with forced=true, should succeed by vm owner
command = """self.virtual_machine.stop({apiclient}, forced=True)"""
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.otheruser_apiclient", command, expected=True)
# 19. Update vm2, should succeed by vm owner
command = """self.virtual_machine.update({apiclient}, displayname = self.virtual_machine.displayname + ".new")"""
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.otheruser_apiclient", command, expected=True)
# 20. Restore vm2, should succeed by vm owner
command = """self.virtual_machine.restore({apiclient})"""
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.otheruser_apiclient", command, expected=True)
# 21. Scale vm2 to another offering, should succeed by vm owner
self.service_offering_new = ServiceOffering.create(
self.apiclient,
self.services["service_offerings"]["big"]
)
self.cleanup.append(self.service_offering_new)
command = """self.virtual_machine.scale_virtualmachine({apiclient}, self.service_offering_new.id)"""
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.otheruser_apiclient", command, expected=True)
# 22. Destroy vm2, should succeed by vm owner
command = """self.virtual_machine.delete({apiclient}, expunge=False)"""
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.otheruser_apiclient", command, expected=True)
# 23. Recover vm2, should succeed by vm owner
allow_expunge_recover_vm = Configurations.list(self.apiclient, name="allow.user.expunge.recover.vm")[0].value
self.logger.debug("Global configuration allow.user.expunge.recover.vm = %s", allow_expunge_recover_vm)
if allow_expunge_recover_vm == "true":
command = """self.virtual_machine.recover({apiclient})"""
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.otheruser_apiclient", command, expected=True)
# 24. Destroy vm2, should succeed by vm owner
command = """self.virtual_machine.delete({apiclient}, expunge=False)"""
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.otheruser_apiclient", command, expected=True)
# 25. Expunge vm2, should succeed by vm owner
if allow_expunge_recover_vm == "true":
command = """self.virtual_machine.expunge({apiclient})"""
self.exec_command("self.user_apiclient", command, expected=False)
self.exec_command("self.otheruser_apiclient", command, expected=True)
else:
self.virtual_machine.expunge(self.apiclient)
# 26. Reset network permissions, should succeed by network owner
command = """self.reset_network_permission({apiclient}, self.user_network, expected=True)"""
self.exec_command("self.otheruser_apiclient", command, expected=False)
self.exec_command("self.user_apiclient", command, expected=True)

View File

@ -30,12 +30,27 @@ _multiprocess_shared_ = True
class TestPVLAN(cloudstackTestCase):
zoneId = 1
networkOfferingId = 7
vlan = 2468
isolatedpvlan = 864
def setUp(self):
self.apiClient = self.testClient.getApiClient()
list_shared_network_offerings = NetworkOffering.list(
self.apiClient,
name="DefaultSharedNetworkOffering",
displayText="Offering for Shared networks"
)
self.assertEqual(
isinstance(list_shared_network_offerings, list),
True,
"List network offerings response was not a valid list"
)
self.assertNotEqual(
len(list_shared_network_offerings),
0,
"List network offerings response was empty"
)
self.networkOfferingId = list_shared_network_offerings[0].id
@attr(tags = ["advanced"], required_hardware="false")
def test_create_pvlan_network(self):

View File

@ -0,0 +1,425 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
"""
Tests of user-private gateway
"""
import logging
import time
from nose.plugins.attrib import attr
from marvin.cloudstackTestCase import cloudstackTestCase
from marvin.lib.utils import cleanup_resources, random_gen
from marvin.lib.base import (Account,
Domain,
Project,
Configurations,
ServiceOffering,
Zone,
Network,
NetworkOffering,
VPC,
VpcOffering,
PrivateGateway)
from marvin.lib.common import (get_domain,
get_zone,
get_template)
NETWORK_STATE_ALLOCATED = "Allocated"
NETWORK_STATE_IMPLEMENTED = "Implemented"
NETWORK_STATE_SETUP = "Setup"
NETWORK_STATE_REMOVED = "Removed"
class TestUserPrivateGateways(cloudstackTestCase):
"""
Test user-shared networks
"""
@classmethod
def setUpClass(cls):
cls.testClient = super(
TestUserPrivateGateways,
cls).getClsTestClient()
cls.apiclient = cls.testClient.getApiClient()
cls.apiclient = cls.testClient.getApiClient()
cls.services = cls.testClient.getParsedTestDataConfig()
zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests())
cls.zone = Zone(zone.__dict__)
cls.template = get_template(cls.apiclient, cls.zone.id)
cls._cleanup = []
cls.logger = logging.getLogger("TestUserPrivateGateways")
cls.stream_handler = logging.StreamHandler()
cls.logger.setLevel(logging.DEBUG)
cls.logger.addHandler(cls.stream_handler)
cls.domain = get_domain(cls.apiclient)
# Create small service offering
cls.service_offering = ServiceOffering.create(
cls.apiclient,
cls.services["service_offerings"]["small"]
)
cls._cleanup.append(cls.service_offering)
# Create network offering for isolated networks
cls.network_offering_isolated = NetworkOffering.create(
cls.apiclient,
cls.services["network_offering"]
)
cls.network_offering_isolated.update(cls.apiclient, state='Enabled')
cls._cleanup.append(cls.network_offering_isolated)
# Create vpc offering
cls.vpc_offering = VpcOffering.create(
cls.apiclient,
cls.services["vpc_offering_multi_lb"])
cls.vpc_offering.update(cls.apiclient, state='Enabled')
cls._cleanup.append(cls.vpc_offering)
# Create network offering for vpc tiers
cls.network_offering_vpc = NetworkOffering.create(
cls.apiclient,
cls.services["nw_offering_isolated_vpc"],
conservemode=False
)
cls.network_offering_vpc.update(cls.apiclient, state='Enabled')
cls._cleanup.append(cls.network_offering_vpc)
# Create sub-domain
cls.sub_domain = Domain.create(
cls.apiclient,
cls.services["acl"]["domain1"]
)
cls._cleanup.append(cls.sub_domain)
# Create domain admin and normal user
cls.domain_admin = Account.create(
cls.apiclient,
cls.services["acl"]["accountD1A"],
admin=True,
domainid=cls.sub_domain.id
)
cls._cleanup.append(cls.domain_admin)
cls.normal_user = Account.create(
cls.apiclient,
cls.services["acl"]["accountD1B"],
domainid=cls.sub_domain.id
)
cls._cleanup.append(cls.normal_user)
# Create project
cls.project = Project.create(
cls.apiclient,
cls.services["project"],
account=cls.domain_admin.name,
domainid=cls.domain_admin.domainid
)
cls._cleanup.append(cls.project)
# Create api clients for domain admin and normal user
cls.domainadmin_user = cls.domain_admin.user[0]
cls.domainapiclient = cls.testClient.getUserApiClient(
cls.domainadmin_user.username, cls.sub_domain.name
)
cls.normaluser_user = cls.normal_user.user[0]
cls.normaluser_apiclient = cls.testClient.getUserApiClient(
cls.normaluser_user.username, cls.sub_domain.name
)
@classmethod
def tearDownClass(cls):
super(TestUserPrivateGateways, cls).tearDownClass()
def setUp(self):
self.cleanup = []
def tearDown(self):
super(TestUserPrivateGateways, self).tearDown()
def delete_network(self, network, apiclient, expected=True):
result = True
try:
Network.delete(
network,
apiclient,
)
except Exception as ex:
result = False
if expected:
self.fail(f"Failed to remove Shared network, but expected to succeed : {ex}")
if result and not expected:
self.fail("network is removed successfully, but expected to fail")
def create_isolated_network_for_account(self, apiclient, domain, account, project, expected=True):
self.services["network"]["name"] = "Test Network Isolated - " + random_gen()
domain_id = None
account_name = None
project_id = None
if domain:
domain_id = domain.id
if account:
account_name = account.name
if project:
project_id = project.id
try:
network = Network.create(
apiclient,
self.services["network"],
domainid=domain_id,
accountid=account_name,
projectid=project_id,
networkofferingid=self.network_offering_isolated.id,
zoneid=self.zone.id
)
except Exception as ex:
network = None
if expected:
self.fail(f"Failed to create Isolated network, but expected to succeed : {ex}")
if network and not expected:
self.fail("Isolated network is created successfully, but expected to fail")
return network
def check_network_state(self, apiclient, network, project, expected_state):
project_id = None
if project:
project_id = project.id
networks = Network.list(
apiclient,
listall=True,
projectid=project_id,
id=network.id
)
if isinstance(networks, list) and len(networks) > 0:
if expected_state == NETWORK_STATE_REMOVED:
self.fail("Found the network, but expected to fail")
if networks[0].state != expected_state:
self.fail(f"Expect network state is {expected_state}, but actual state is {networks[0].state}")
elif expected_state != NETWORK_STATE_REMOVED:
self.fail("Failed to find the network, but expected to succeed")
def create_vpc_for_account(self, apiclient, domain, account, project):
self.services["vpc"]["name"] = "Test VPC - " + random_gen()
self.services["vpc"]["cidr"] = "10.1.0.0/20"
domain_id = None
account_name = None
if domain:
domain_id = domain.id
if account:
account_name = account.name
project_id = None
if project:
project_id = project.id
vpc = VPC.create(
apiclient,
self.services["vpc"],
domainid=domain_id,
accountid=account_name,
projectid=project_id,
vpcofferingid=self.vpc_offering.id,
zoneid=self.zone.id,
start=False
)
return vpc
def create_vpc_tier_for_account(self, apiclient, vpc, project=None, gateway = '10.1.1.1'):
self.services["network"]["name"] = "Test VPC tier - " + random_gen()
project_id = None
if project:
project_id = project.id
vpc_tier = Network.create(
apiclient,
self.services["network"],
networkofferingid=self.network_offering_vpc.id,
zoneid=self.zone.id,
projectid=project_id,
gateway=gateway,
netmask="255.255.255.0",
vpcid=vpc.id
)
return vpc_tier
def create_vpc_private_gateway(self, apiclient, vpc, vlan_id, associated_network=None, expected=True):
self.services["private_gateway"]["name"] = "Test Network Isolated - " + random_gen()
associated_network_id = None
if associated_network:
associated_network_id = associated_network.id
private_gateway = None
try:
private_gateway = PrivateGateway.create(
apiclient,
vpcid=vpc.id,
gateway = self.services["private_gateway"]["gateway"],
ipaddress = self.services["private_gateway"]["ipaddress"],
netmask = self.services["private_gateway"]["netmask"],
vlan = vlan_id,
associatednetworkid = associated_network_id
)
except Exception as ex:
private_gateway = None
if expected:
self.fail(f"Failed to create private gateway, but expected to succeed : {ex}")
if private_gateway and not expected:
self.fail("private gateway is created successfully, but expected to fail")
return private_gateway
def delete_vpc_private_gateway(self, apiclient, private_gateway, expected=True):
result = True
try:
private_gateway.delete(apiclient)
except Exception as ex:
result = False
if expected:
self.fail(f"Failed to remove private gateway, but expected to succeed : {ex}")
if result and not expected:
self.fail("private gateway is removed successfully, but expected to fail")
def delete_vpc(self, apiclient, vpc, expected=True):
result = True
try:
vpc.delete(apiclient)
except Exception as ex:
result = False
if expected:
self.fail(f"Failed to remove VPC, but expected to succeed : {ex}")
if result and not expected:
self.fail("VPC is removed successfully, but expected to fail")
@attr(tags=["advanced"], required_hardware="false")
def test_01_create_private_gateway_with_vlan(self):
""" Create private gateway with vlan """
# Create VPC
vpc1 = self.create_vpc_for_account(self.apiclient, None, None, None)
vpc2 = self.create_vpc_for_account(self.domainapiclient, None, None, None)
vpc3 = self.create_vpc_for_account(self.normaluser_apiclient, None, None, None)
vpc4 = self.create_vpc_for_account(self.domainapiclient, None, None, self.project)
# Create VPC private gateway with vlan (can only be done by ROOT admin)
private_gateway1 = self.create_vpc_private_gateway(self.apiclient, vpc1, 10, None, True)
self.create_vpc_private_gateway(self.domainapiclient, vpc2, 11, None, False)
self.create_vpc_private_gateway(self.normaluser_apiclient, vpc3, 12, None, False)
self.create_vpc_private_gateway(self.domainapiclient, vpc4, 13, None, False)
private_gateway2 = self.create_vpc_private_gateway(self.apiclient, vpc2, 11, None, True)
private_gateway3 = self.create_vpc_private_gateway(self.apiclient, vpc3, 12, None, True)
private_gateway4 = self.create_vpc_private_gateway(self.apiclient, vpc4, 13, None, True)
# Delete VPC private gateway (should succeed by ROOT admin)
self.delete_vpc_private_gateway(self.apiclient, private_gateway1, True)
self.delete_vpc_private_gateway(self.domainapiclient, private_gateway2, False)
self.delete_vpc_private_gateway(self.normaluser_apiclient, private_gateway2, False)
self.delete_vpc_private_gateway(self.domainapiclient, private_gateway4, False)
self.delete_vpc_private_gateway(self.apiclient, private_gateway2, True)
self.delete_vpc_private_gateway(self.apiclient, private_gateway3, True)
self.delete_vpc_private_gateway(self.apiclient, private_gateway4, True)
# Delete VPC
self.delete_vpc(self.apiclient, vpc1)
self.delete_vpc(self.domainapiclient, vpc2)
self.delete_vpc(self.normaluser_apiclient, vpc3)
self.delete_vpc(self.domainapiclient, vpc4)
@attr(tags=["advanced"], required_hardware="false")
def test_02_create_private_gateway_with_associated_network(self):
""" Create private gateway with associated network """
self.services["network"]["networkoffering"] = self.network_offering_isolated.id
self.services["network"]["vlan"] = None
# Create isolated networks
isolated_network1 = self.create_isolated_network_for_account(self.apiclient, None, None, None)
isolated_network2 = self.create_isolated_network_for_account(self.apiclient, self.sub_domain, self.domain_admin, None)
isolated_network3 = self.create_isolated_network_for_account(self.apiclient, self.sub_domain, self.normal_user, None)
isolated_network4 = self.create_isolated_network_for_account(self.apiclient, self.sub_domain, None, self.project)
# Check state of isolated networks (should be Allocated)
self.check_network_state(self.apiclient, isolated_network1, None, NETWORK_STATE_ALLOCATED)
self.check_network_state(self.domainapiclient, isolated_network2, None, NETWORK_STATE_ALLOCATED)
self.check_network_state(self.normaluser_apiclient, isolated_network3, None, NETWORK_STATE_ALLOCATED)
self.check_network_state(self.domainapiclient, isolated_network4, self.project, NETWORK_STATE_ALLOCATED)
# Create VPC
vpc1 = self.create_vpc_for_account(self.apiclient, None, None, None)
vpc2 = self.create_vpc_for_account(self.domainapiclient, None, None, None)
vpc3 = self.create_vpc_for_account(self.normaluser_apiclient, None, None, None)
vpc4 = self.create_vpc_for_account(self.domainapiclient, None, None, self.project)
# Create VPC tier
vpc1_tier1 = self.create_vpc_tier_for_account(self.apiclient, vpc1)
vpc2_tier1 = self.create_vpc_tier_for_account(self.domainapiclient, vpc2)
vpc3_tier1 = self.create_vpc_tier_for_account(self.normaluser_apiclient, vpc3)
vpc4_tier1 = self.create_vpc_tier_for_account(self.domainapiclient, vpc4, self.project)
# Create VPC private gateway with associated network (can be done by ROOT admin / domain admin / normal user)
private_gateway1 = self.create_vpc_private_gateway(self.apiclient, vpc1, None, isolated_network1, True)
private_gateway2 = self.create_vpc_private_gateway(self.domainapiclient, vpc2, None, isolated_network2, True)
private_gateway3 = self.create_vpc_private_gateway(self.normaluser_apiclient, vpc3, None, isolated_network3, True)
private_gateway4 = self.create_vpc_private_gateway(self.domainapiclient, vpc4, None, isolated_network4, True)
# Check state of isolated networks (should be Implemented)
self.check_network_state(self.apiclient, isolated_network1, None, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.domainapiclient, isolated_network2, None, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.normaluser_apiclient, isolated_network3, None, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.domainapiclient, isolated_network4, self.project, NETWORK_STATE_IMPLEMENTED)
# Delete VPC private gateway of domain admin (should succeed)
self.delete_vpc_private_gateway(self.domainapiclient, private_gateway2, True)
# Wait for network GC to shut down the isolated networks
gc_wait = Configurations.list(self.apiclient, name="network.gc.wait")
gc_interval = Configurations.list(self.apiclient, name="network.gc.interval")
total_sleep = 360
if gc_wait and gc_interval:
self.logger.debug("network.gc.wait is ==> %s", gc_wait[0].value)
self.logger.debug("network.gc.interval is ==> %s", gc_interval[0].value)
total_sleep = max(int(gc_wait[0].value), int(gc_interval[0].value)) * 2 + 60
else:
self.logger.debug("Could not retrieve the keys 'network.gc.interval' and 'network.gc.wait'. Sleeping for 6 minutes.")
time.sleep(total_sleep)
# Check state of isolated networks (1 should be Allocated, 2 should still be Implemented)
self.check_network_state(self.apiclient, isolated_network1, None, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.domainapiclient, isolated_network2, None, NETWORK_STATE_ALLOCATED)
self.check_network_state(self.normaluser_apiclient, isolated_network3, None, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.domainapiclient, isolated_network4, self.project, NETWORK_STATE_IMPLEMENTED)
# Delete 2 VPC private gateway (should succeed)
self.delete_vpc_private_gateway(self.apiclient, private_gateway1, True)
self.delete_vpc_private_gateway(self.apiclient, private_gateway3, True)
self.delete_vpc_private_gateway(self.apiclient, private_gateway4, True)
# Delete VPC tiers (should succeed)
self.delete_network(vpc1_tier1, self.apiclient, True)
self.delete_network(vpc2_tier1, self.domainapiclient, True)
self.delete_network(vpc3_tier1, self.normaluser_apiclient, True)
self.delete_network(vpc4_tier1, self.domainapiclient, True)
# Delete VPC
self.delete_vpc(self.apiclient, vpc1)
self.delete_vpc(self.domainapiclient, vpc2)
self.delete_vpc(self.normaluser_apiclient, vpc3)
self.delete_vpc(self.domainapiclient, vpc4)
# Delete isolated networks (should succeed)
self.delete_network(isolated_network1, self.apiclient, True)
self.delete_network(isolated_network2, self.domainapiclient, True)
self.delete_network(isolated_network3, self.normaluser_apiclient, True)
self.delete_network(isolated_network4, self.domainapiclient, True)

View File

@ -0,0 +1,631 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
"""
Tests of user-shared networks
"""
import logging
import time
from nose.plugins.attrib import attr
from marvin.cloudstackTestCase import cloudstackTestCase
from marvin.lib.utils import cleanup_resources, random_gen
from marvin.lib.base import (Account,
Domain,
Project,
Configurations,
ServiceOffering,
Zone,
Network,
NetworkOffering,
VPC,
VpcOffering)
from marvin.lib.common import (get_domain,
get_zone,
get_template)
NETWORK_STATE_ALLOCATED = "Allocated"
NETWORK_STATE_IMPLEMENTED = "Implemented"
NETWORK_STATE_SETUP = "Setup"
NETWORK_STATE_REMOVED = "Removed"
class TestUserSharedNetworks(cloudstackTestCase):
"""
Test user-shared networks
"""
@classmethod
def setUpClass(cls):
cls.testClient = super(
TestUserSharedNetworks,
cls).getClsTestClient()
cls.apiclient = cls.testClient.getApiClient()
cls.services = cls.testClient.getParsedTestDataConfig()
zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests())
cls.zone = Zone(zone.__dict__)
cls.template = get_template(cls.apiclient, cls.zone.id)
cls._cleanup = []
cls.logger = logging.getLogger("TestUserSharedNetworks")
cls.stream_handler = logging.StreamHandler()
cls.logger.setLevel(logging.DEBUG)
cls.logger.addHandler(cls.stream_handler)
cls.domain = get_domain(cls.apiclient)
# Create small service offering
cls.service_offering = ServiceOffering.create(
cls.apiclient,
cls.services["service_offerings"]["small"]
)
cls._cleanup.append(cls.service_offering)
# Create network offering for user-shared networks (specifyVlan=true)
cls.network_offering_withvlan = NetworkOffering.create(
cls.apiclient,
cls.services["network_offering_shared"]
)
cls.network_offering_withvlan.update(cls.apiclient, state='Enabled')
cls._cleanup.append(cls.network_offering_withvlan)
# Create network offering for user-shared networks (specifyVlan=false)
cls.services["network_offering_shared"]["specifyVlan"] = "False"
cls.network_offering_novlan = NetworkOffering.create(
cls.apiclient,
cls.services["network_offering_shared"]
)
cls.network_offering_novlan.update(cls.apiclient, state='Enabled')
cls._cleanup.append(cls.network_offering_novlan)
# Create network offering for isolated networks
cls.network_offering_isolated = NetworkOffering.create(
cls.apiclient,
cls.services["network_offering"]
)
cls.network_offering_isolated.update(cls.apiclient, state='Enabled')
cls._cleanup.append(cls.network_offering_isolated)
# Create vpc offering
cls.vpc_offering = VpcOffering.create(
cls.apiclient,
cls.services["vpc_offering_multi_lb"])
cls.vpc_offering.update(cls.apiclient, state='Enabled')
cls._cleanup.append(cls.vpc_offering)
# Create network offering for vpc tiers
cls.network_offering_vpc = NetworkOffering.create(
cls.apiclient,
cls.services["nw_offering_isolated_vpc"],
conservemode=False
)
cls.network_offering_vpc.update(cls.apiclient, state='Enabled')
cls._cleanup.append(cls.network_offering_vpc)
# Create sub-domain
cls.sub_domain = Domain.create(
cls.apiclient,
cls.services["acl"]["domain1"]
)
cls._cleanup.append(cls.sub_domain)
# Create domain admin and normal user
cls.domain_admin = Account.create(
cls.apiclient,
cls.services["acl"]["accountD1A"],
admin=True,
domainid=cls.sub_domain.id
)
cls._cleanup.append(cls.domain_admin)
cls.normal_user = Account.create(
cls.apiclient,
cls.services["acl"]["accountD1B"],
domainid=cls.sub_domain.id
)
cls._cleanup.append(cls.normal_user)
# Create project
cls.project = Project.create(
cls.apiclient,
cls.services["project"],
account=cls.domain_admin.name,
domainid=cls.domain_admin.domainid
)
cls._cleanup.append(cls.project)
# Create api clients for domain admin and normal user
cls.domainadmin_user = cls.domain_admin.user[0]
cls.domainapiclient = cls.testClient.getUserApiClient(
cls.domainadmin_user.username, cls.sub_domain.name
)
cls.normaluser_user = cls.normal_user.user[0]
cls.normaluser_apiclient = cls.testClient.getUserApiClient(
cls.normaluser_user.username, cls.sub_domain.name
)
@classmethod
def tearDownClass(cls):
super(TestUserSharedNetworks, cls).tearDownClass()
def setUp(self):
self.cleanup = []
def tearDown(self):
super(TestUserSharedNetworks, self).tearDown()
def create_shared_network_for_account(self, apiclient, domain, account, expected=True):
return self.create_shared_network_with_associated_network(apiclient, domain, account, None, None, expected)
def create_shared_network_with_associated_network_for_domain(self, apiclient, domain, associated_network, expected=True):
return self.create_shared_network_with_associated_network(apiclient, domain, None, None, associated_network, expected)
def create_shared_network_with_associated_network_for_caller(self, apiclient, project, associated_network, expected=True):
return self.create_shared_network_with_associated_network(apiclient, None, None, project, associated_network, expected)
def create_shared_network_with_associated_network(self, apiclient, domain, account, project, associated_network, expected=True):
self.services["network2"]["acltype"] = "Account"
self.services["network2"]["name"] = "Test Network Shared - " + random_gen()
domain_id = None
account_name = None
project_id = None
if domain:
self.services["network2"]["acltype"] = "Domain"
domain_id = domain.id
if account:
self.services["network2"]["acltype"] = "Account"
account_name = account.name
if project:
self.services["network2"]["acltype"] = "Account"
project_id = project.id
associated_network_id = None
if associated_network:
associated_network_id = associated_network.id
try:
network = Network.create(
apiclient,
self.services["network2"],
domainid=domain_id,
accountid=account_name,
projectid=project_id,
associatednetworkid=associated_network_id,
zoneid=self.zone.id
)
except Exception as ex:
network = None
if expected:
self.fail(f"Failed to create Shared network, but expected to succeed : {ex}")
if network and not expected:
self.fail("Shared network is created successfully, but expected to fail")
return network
def delete_network(self, network, apiclient, expected=True):
result = True
try:
Network.delete(
network,
apiclient,
)
except Exception as ex:
result = False
if expected:
self.fail(f"Failed to remove Shared network, but expected to succeed : {ex}")
if result and not expected:
self.fail("network is removed successfully, but expected to fail")
def create_isolated_network_for_account(self, apiclient, domain, account, project, expected=True):
self.services["network"]["name"] = "Test Network Isolated - " + random_gen()
domain_id = None
account_name = None
project_id = None
if domain:
domain_id = domain.id
if account:
account_name = account.name
if project:
project_id = project.id
try:
network = Network.create(
apiclient,
self.services["network"],
domainid=domain_id,
accountid=account_name,
projectid=project_id,
networkofferingid=self.network_offering_isolated.id,
zoneid=self.zone.id
)
except Exception as ex:
network = None
if expected:
self.fail(f"Failed to create Isolated network, but expected to succeed : {ex}")
if network and not expected:
self.fail("Isolated network is created successfully, but expected to fail")
return network
def check_network_state(self, apiclient, network, project, expected_state):
project_id = None
if project:
project_id = project.id
networks = Network.list(
apiclient,
listall=True,
projectid=project_id,
id=network.id
)
if isinstance(networks, list) and len(networks) > 0:
if expected_state == NETWORK_STATE_REMOVED:
self.fail("Found the network, but expected to fail")
if networks[0].state != expected_state:
self.fail(f"Expect network state is {expected_state}, but actual state is {networks[0].state}")
elif expected_state != NETWORK_STATE_REMOVED:
self.fail("Failed to find the network, but expected to succeed")
def create_vpc_for_account(self, apiclient, domain, account, project):
self.services["vpc"]["name"] = "Test VPC - " + random_gen()
self.services["vpc"]["displaytext"] = self.services["vpc"]["name"]
self.services["vpc"]["cidr"] = "10.1.0.0/20"
domain_id = None
account_name = None
if domain:
domain_id = domain.id
if account:
account_name = account.name
project_id = None
if project:
project_id = project.id
vpc = VPC.create(
apiclient,
self.services["vpc"],
domainid=domain_id,
accountid=account_name,
projectid=project_id,
vpcofferingid=self.vpc_offering.id,
zoneid=self.zone.id,
start=False
)
return vpc
def create_vpc_tier_for_account(self, apiclient, vpc, project=None, gateway = '10.1.1.1'):
self.services["network"]["name"] = "Test VPC tier - " + random_gen()
project_id = None
if project:
project_id = project.id
vpc_tier = Network.create(
apiclient,
self.services["network"],
networkofferingid=self.network_offering_vpc.id,
zoneid=self.zone.id,
projectid=project_id,
gateway=gateway,
netmask="255.255.255.0",
vpcid=vpc.id
)
return vpc_tier
def delete_vpc(self, apiclient, vpc, expected=True):
result = True
try:
vpc.delete(apiclient)
except Exception as ex:
result = False
if expected:
self.fail(f"Failed to remove VPC, but expected to succeed : {ex}")
if result and not expected:
self.fail("VPC is removed successfully, but expected to fail")
@attr(tags=["advanced"], required_hardware="false")
def test_01_create_user_shared_network_without_vlan(self):
""" Create user-shared networks without vlan """
self.services["network2"]["networkoffering"] = self.network_offering_novlan.id
self.services["network2"]["vlan"] = None
network1 = self.create_shared_network_for_account(self.apiclient, None, None)
network2 = self.create_shared_network_for_account(self.domainapiclient, None, None)
network3 = self.create_shared_network_for_account(self.normaluser_apiclient, None, None)
self.delete_network(network1, self.apiclient)
self.delete_network(network2, self.domainapiclient)
self.delete_network(network3, self.normaluser_apiclient)
network4 = self.create_shared_network_for_account(self.domainapiclient, self.sub_domain, self.normal_user, True)
self.delete_network(network4, self.normaluser_apiclient)
network5 = self.create_shared_network_for_account(self.apiclient, self.sub_domain, None, True)
self.delete_network(network5, self.apiclient)
network6 = self.create_shared_network_for_account(self.domainapiclient, self.sub_domain, None, True)
self.delete_network(network6, self.apiclient)
self.create_shared_network_for_account(self.normaluser_apiclient, self.sub_domain, None, False)
@attr(tags=["advanced"], required_hardware="false")
def test_02_create_shared_network_with_vlan(self):
""" Create shared networks with vlan
Only be created/deleted by root admin, Cannot create networks with same vlan
"""
self.services["network2"]["networkoffering"] = self.network_offering_withvlan.id
self.services["network2"]["vlan"] = 4000
self.create_shared_network_for_account(self.domainapiclient, self.sub_domain, None, False)
self.create_shared_network_for_account(self.normaluser_apiclient, self.sub_domain, None, False)
network1 = self.create_shared_network_for_account(self.apiclient, self.sub_domain, None, True)
self.create_shared_network_for_account(self.apiclient, self.sub_domain, self.normal_user, False)
self.delete_network(network1, self.domainapiclient, False)
self.delete_network(network1, self.apiclient, True)
self.create_shared_network_for_account(self.domainapiclient, self.sub_domain, self.normal_user, False)
self.create_shared_network_for_account(self.normaluser_apiclient, self.sub_domain, self.normal_user, False)
network2 = self.create_shared_network_for_account(self.apiclient, self.sub_domain, self.normal_user, True)
self.delete_network(network2, self.domainapiclient, False)
self.delete_network(network2, self.normaluser_apiclient, False)
self.delete_network(network2, self.apiclient, True)
@attr(tags=["advanced"], required_hardware="false")
def test_03_create_domain_shared_network_with_associated_network(self):
""" Create domain-level shared networks with associated network """
self.services["network2"]["networkoffering"] = self.network_offering_novlan.id
self.services["network2"]["vlan"] = None
# Create isolated networks
isolated_network1 = self.create_isolated_network_for_account(self.apiclient, None, None, None, True)
isolated_network2 = self.create_isolated_network_for_account(self.apiclient, self.sub_domain, self.domain_admin, None, True)
isolated_network3 = self.create_isolated_network_for_account(self.apiclient, self.sub_domain, self.normal_user, None, True)
isolated_network4 = self.create_isolated_network_for_account(self.apiclient, self.sub_domain, None, self.project, True)
# Create domain-level shared network with associated_network (caller must be root admin/domain admin, must be in same domain)
self.create_shared_network_with_associated_network_for_domain(self.apiclient, self.sub_domain, isolated_network1, False)
self.create_shared_network_with_associated_network_for_domain(self.domainapiclient, self.sub_domain, isolated_network1, False)
self.create_shared_network_with_associated_network_for_domain(self.normaluser_apiclient, self.sub_domain, isolated_network1, False)
self.create_shared_network_with_associated_network_for_domain(self.normaluser_apiclient, self.sub_domain, isolated_network2, False)
self.create_shared_network_with_associated_network_for_domain(self.normaluser_apiclient, self.sub_domain, isolated_network3, False)
self.create_shared_network_with_associated_network_for_domain(self.normaluser_apiclient, self.sub_domain, isolated_network4, False)
shared_network1 = self.create_shared_network_with_associated_network_for_domain(self.apiclient, self.domain, isolated_network1, True)
shared_network2 = self.create_shared_network_with_associated_network_for_domain(self.domainapiclient, self.sub_domain, isolated_network2, True)
shared_network3 = self.create_shared_network_with_associated_network_for_domain(self.domainapiclient, self.sub_domain, isolated_network3, True)
shared_network4 = self.create_shared_network_with_associated_network_for_domain(self.domainapiclient, self.sub_domain, isolated_network4, True)
# Check state of isolated networks (should be Implemented)
self.check_network_state(self.apiclient, isolated_network1, None, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.domainapiclient, isolated_network2, None, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.normaluser_apiclient, isolated_network3, None, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.domainapiclient, isolated_network4, self.project, NETWORK_STATE_IMPLEMENTED)
# Delete isolated networks (should fail)
self.delete_network(isolated_network1, self.apiclient, False)
self.delete_network(isolated_network2, self.apiclient, False)
self.delete_network(isolated_network3, self.apiclient, False)
self.delete_network(isolated_network4, self.apiclient, False)
# Create VPC
vpc1 = self.create_vpc_for_account(self.apiclient, None, None, None)
vpc2 = self.create_vpc_for_account(self.domainapiclient, None, None, None)
vpc3 = self.create_vpc_for_account(self.normaluser_apiclient, None, None, None)
vpc4 = self.create_vpc_for_account(self.domainapiclient, None, None, self.project)
# Create VPC tier
vpc1_tier1 = self.create_vpc_tier_for_account(self.apiclient, vpc1)
vpc2_tier1 = self.create_vpc_tier_for_account(self.domainapiclient, vpc2)
vpc3_tier1 = self.create_vpc_tier_for_account(self.normaluser_apiclient, vpc3)
vpc4_tier1 = self.create_vpc_tier_for_account(self.domainapiclient, vpc4, self.project)
# Create domain-level shared network with associated vpc tier (caller must be root admin/domain admin, must be in same domain)
self.create_shared_network_with_associated_network_for_domain(self.apiclient, self.sub_domain, vpc1_tier1, False)
self.create_shared_network_with_associated_network_for_domain(self.domainapiclient, self.sub_domain, vpc1_tier1, False)
self.create_shared_network_with_associated_network_for_domain(self.normaluser_apiclient, self.sub_domain, vpc1_tier1, False)
self.create_shared_network_with_associated_network_for_domain(self.normaluser_apiclient, self.sub_domain, vpc2_tier1, False)
self.create_shared_network_with_associated_network_for_domain(self.normaluser_apiclient, self.sub_domain, vpc3_tier1, False)
self.create_shared_network_with_associated_network_for_domain(self.normaluser_apiclient, self.sub_domain, vpc4_tier1, False)
shared_network_vpctier1 = self.create_shared_network_with_associated_network_for_domain(self.apiclient, self.domain, vpc1_tier1, True)
shared_network_vpctier2 = self.create_shared_network_with_associated_network_for_domain(self.domainapiclient, self.sub_domain, vpc2_tier1, True)
shared_network_vpctier3 = self.create_shared_network_with_associated_network_for_domain(self.domainapiclient, self.sub_domain, vpc3_tier1, True)
shared_network_vpctier4 = self.create_shared_network_with_associated_network_for_domain(self.domainapiclient, self.sub_domain, vpc4_tier1, True)
# Check state of vpc tiers (should be Implemented)
self.check_network_state(self.apiclient, vpc1_tier1, None, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.domainapiclient, vpc2_tier1, None, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.normaluser_apiclient, vpc3_tier1, None, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.domainapiclient, vpc4_tier1, self.project, NETWORK_STATE_IMPLEMENTED)
# Delete vpc tiers(should fail)
self.delete_network(vpc1_tier1, self.apiclient, False)
self.delete_network(vpc2_tier1, self.apiclient, False)
self.delete_network(vpc3_tier1, self.apiclient, False)
self.delete_network(vpc4_tier1, self.apiclient, False)
# Delete shared networks associated to domain admin's isolated network or vpc tier(should succeed)
self.delete_network(shared_network2, self.domainapiclient, True)
self.delete_network(shared_network_vpctier2, self.domainapiclient, True)
# Wait for network GC to shut down the isolated networks
gc_wait = Configurations.list(self.apiclient, name="network.gc.wait")
gc_interval = Configurations.list(self.apiclient, name="network.gc.interval")
total_sleep = 360
if gc_wait and gc_interval:
self.logger.debug("network.gc.wait is ==> %s", gc_wait[0].value)
self.logger.debug("network.gc.interval is ==> %s", gc_interval[0].value)
total_sleep = max(int(gc_wait[0].value), int(gc_interval[0].value)) * 2 + 60
else:
self.logger.debug("Could not retrieve the keys 'network.gc.interval' and 'network.gc.wait'. Sleeping for 6 minutes.")
time.sleep(total_sleep)
# Check state of isolated networks (1 should be Allocated, 3 should still be Implemented)
self.check_network_state(self.apiclient, isolated_network1, None, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.domainapiclient, isolated_network2, None, NETWORK_STATE_ALLOCATED)
self.check_network_state(self.normaluser_apiclient, isolated_network3, None, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.domainapiclient, isolated_network4, self.project, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.apiclient, vpc1_tier1, None, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.domainapiclient, vpc2_tier1, None, NETWORK_STATE_ALLOCATED)
self.check_network_state(self.normaluser_apiclient, vpc3_tier1, None, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.domainapiclient, vpc4_tier1, self.project, NETWORK_STATE_IMPLEMENTED)
# Check state of shared network (should be Setup)
self.check_network_state(self.apiclient, shared_network1, None, NETWORK_STATE_SETUP)
self.check_network_state(self.normaluser_apiclient, shared_network3, None, NETWORK_STATE_SETUP)
self.check_network_state(self.domainapiclient, shared_network4, None, NETWORK_STATE_SETUP)
self.check_network_state(self.apiclient, shared_network_vpctier1, None, NETWORK_STATE_SETUP)
self.check_network_state(self.normaluser_apiclient, shared_network_vpctier3, None, NETWORK_STATE_SETUP)
self.check_network_state(self.domainapiclient, shared_network_vpctier4, None, NETWORK_STATE_SETUP)
# Delete admin's shared networks (should succeed)
self.delete_network(shared_network1, self.apiclient, True)
self.delete_network(shared_network3, self.domainapiclient, True)
self.delete_network(shared_network4, self.domainapiclient, True)
self.delete_network(shared_network_vpctier1, self.apiclient, True)
self.delete_network(shared_network_vpctier3, self.domainapiclient, True)
self.delete_network(shared_network_vpctier4, self.domainapiclient, True)
# Delete admin's and domain admin's isolated network, but keep the normal user's network
# normal user's shared network and isolated network should be removed in tearDown successfully
self.delete_network(isolated_network1, self.apiclient, True)
self.delete_network(isolated_network2, self.domainapiclient, True)
self.delete_network(vpc1_tier1, self.apiclient, True)
self.delete_vpc(self.apiclient, vpc1)
@attr(tags=["advanced"], required_hardware="false")
def test_04_create_account_shared_network_with_associated_network(self):
""" Create account-level shared networks with associated network """
self.services["network2"]["networkoffering"] = self.network_offering_novlan.id
self.services["network2"]["vlan"] = None
# Create isolated networks
isolated_network1 = self.create_isolated_network_for_account(self.apiclient, None, None, None, True)
isolated_network2 = self.create_isolated_network_for_account(self.apiclient, self.sub_domain, self.domain_admin, None, True)
isolated_network3 = self.create_isolated_network_for_account(self.apiclient, self.sub_domain, self.normal_user, None, True)
isolated_network4 = self.create_isolated_network_for_account(self.apiclient, self.sub_domain, None, self.project, True)
# Check state of isolated networks (should be Allocated)
self.check_network_state(self.apiclient, isolated_network1, None, NETWORK_STATE_ALLOCATED)
self.check_network_state(self.domainapiclient, isolated_network2, None, NETWORK_STATE_ALLOCATED)
self.check_network_state(self.normaluser_apiclient, isolated_network3, None, NETWORK_STATE_ALLOCATED)
self.check_network_state(self.domainapiclient, isolated_network4, self.project, NETWORK_STATE_ALLOCATED)
# Create shared networks with associated network (must be same owner)
self.create_shared_network_with_associated_network_for_caller(self.domainapiclient, None, isolated_network1, False)
self.create_shared_network_with_associated_network_for_caller(self.domainapiclient, None, isolated_network3, False)
self.create_shared_network_with_associated_network_for_caller(self.domainapiclient, None, isolated_network4, False)
self.create_shared_network_with_associated_network_for_caller(self.normaluser_apiclient, None, isolated_network1, False)
self.create_shared_network_with_associated_network_for_caller(self.normaluser_apiclient, None, isolated_network2, False)
self.create_shared_network_with_associated_network_for_caller(self.normaluser_apiclient, None, isolated_network4, False)
shared_network1 = self.create_shared_network_with_associated_network_for_caller(self.apiclient, None, isolated_network1, True)
shared_network2 = self.create_shared_network_with_associated_network_for_caller(self.domainapiclient, None, isolated_network2, True)
shared_network3 = self.create_shared_network_with_associated_network_for_caller(self.normaluser_apiclient, None, isolated_network3, True)
shared_network4 = self.create_shared_network_with_associated_network_for_caller(self.domainapiclient, self.project, isolated_network4, True)
# Check state of isolated networks (should be Implemented)
self.check_network_state(self.apiclient, isolated_network1, None, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.domainapiclient, isolated_network2, None, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.normaluser_apiclient, isolated_network3, None, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.domainapiclient, isolated_network4, self.project, NETWORK_STATE_IMPLEMENTED)
# Delete isolated networks (should fail)
self.delete_network(isolated_network1, self.apiclient, False)
self.delete_network(isolated_network2, self.apiclient, False)
self.delete_network(isolated_network3, self.apiclient, False)
self.delete_network(isolated_network4, self.apiclient, False)
# Create VPC
vpc1 = self.create_vpc_for_account(self.apiclient, None, None, None)
vpc2 = self.create_vpc_for_account(self.domainapiclient, None, None, None)
vpc3 = self.create_vpc_for_account(self.normaluser_apiclient, None, None, None)
vpc4 = self.create_vpc_for_account(self.domainapiclient, None, None, self.project)
# Create VPC tier
vpc1_tier1 = self.create_vpc_tier_for_account(self.apiclient, vpc1)
vpc2_tier1 = self.create_vpc_tier_for_account(self.domainapiclient, vpc2)
vpc3_tier1 = self.create_vpc_tier_for_account(self.normaluser_apiclient, vpc3)
vpc4_tier1 = self.create_vpc_tier_for_account(self.domainapiclient, vpc4, self.project)
# Create account-level shared network with associated vpc tier (caller must be root admin/domain admin, must be in same domain)
self.create_shared_network_with_associated_network_for_caller(self.domainapiclient, None, vpc1_tier1, False)
self.create_shared_network_with_associated_network_for_caller(self.domainapiclient, None, vpc3_tier1, False)
self.create_shared_network_with_associated_network_for_caller(self.domainapiclient, None, vpc4_tier1, False)
self.create_shared_network_with_associated_network_for_caller(self.normaluser_apiclient, None, vpc1_tier1, False)
self.create_shared_network_with_associated_network_for_caller(self.normaluser_apiclient, None, vpc2_tier1, False)
self.create_shared_network_with_associated_network_for_caller(self.normaluser_apiclient, None, vpc4_tier1, False)
shared_network_vpctier1 = self.create_shared_network_with_associated_network_for_caller(self.apiclient, None, vpc1_tier1, True)
shared_network_vpctier2 = self.create_shared_network_with_associated_network_for_caller(self.domainapiclient, None, vpc2_tier1, True)
shared_network_vpctier3 = self.create_shared_network_with_associated_network_for_caller(self.normaluser_apiclient, None, vpc3_tier1, True)
shared_network_vpctier4 = self.create_shared_network_with_associated_network_for_caller(self.domainapiclient, self.project, vpc4_tier1, True)
# Check state of vpc tiers (should be Implemented)
self.check_network_state(self.apiclient, vpc1_tier1, None, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.domainapiclient, vpc2_tier1, None, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.normaluser_apiclient, vpc3_tier1, None, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.domainapiclient, vpc4_tier1, self.project, NETWORK_STATE_IMPLEMENTED)
# Delete vpc tiers(should fail)
self.delete_network(vpc1_tier1, self.apiclient, False)
self.delete_network(vpc2_tier1, self.apiclient, False)
self.delete_network(vpc3_tier1, self.apiclient, False)
self.delete_network(vpc4_tier1, self.apiclient, False)
# Delete shared networks associated to domain admin's isolated network or vpc tier(should succeed)
self.delete_network(shared_network2, self.domainapiclient, True)
self.delete_network(shared_network_vpctier2, self.domainapiclient, True)
# Wait for network GC to shut down the isolated networks
gc_wait = Configurations.list(self.apiclient, name="network.gc.wait")
gc_interval = Configurations.list(self.apiclient, name="network.gc.interval")
total_sleep = 360
if gc_wait and gc_interval:
self.logger.debug("network.gc.wait is ==> %s", gc_wait[0].value)
self.logger.debug("network.gc.interval is ==> %s", gc_interval[0].value)
total_sleep = max(int(gc_wait[0].value), int(gc_interval[0].value)) * 2 + 60
else:
self.logger.debug("Could not retrieve the keys 'network.gc.interval' and 'network.gc.wait'. Sleeping for 6 minutes.")
time.sleep(total_sleep)
# Check state of isolated networks (1 should be Allocated, 3 should still be Implemented)
self.check_network_state(self.apiclient, isolated_network1, None, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.domainapiclient, isolated_network2, None, NETWORK_STATE_ALLOCATED)
self.check_network_state(self.normaluser_apiclient, isolated_network3, None, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.domainapiclient, isolated_network4, self.project, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.apiclient, vpc1_tier1, None, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.domainapiclient, vpc2_tier1, None, NETWORK_STATE_ALLOCATED)
self.check_network_state(self.normaluser_apiclient, vpc3_tier1, None, NETWORK_STATE_IMPLEMENTED)
self.check_network_state(self.domainapiclient, vpc4_tier1, self.project, NETWORK_STATE_IMPLEMENTED)
# Check state of shared network (should be Setup)
self.check_network_state(self.apiclient, shared_network1, None, NETWORK_STATE_SETUP)
self.check_network_state(self.normaluser_apiclient, shared_network3, None, NETWORK_STATE_SETUP)
self.check_network_state(self.domainapiclient, shared_network4, self.project, NETWORK_STATE_SETUP)
self.check_network_state(self.apiclient, shared_network_vpctier1, None, NETWORK_STATE_SETUP)
self.check_network_state(self.normaluser_apiclient, shared_network_vpctier3, None, NETWORK_STATE_SETUP)
self.check_network_state(self.domainapiclient, shared_network_vpctier4, self.project, NETWORK_STATE_SETUP)
# Delete admin's shared networks (should succeed)
self.delete_network(shared_network1, self.apiclient, True)
self.delete_network(shared_network_vpctier1, self.apiclient, True)
# Delete admin's and domain admin's isolated network, but keep the normal user's network
# normal user's shared network and isolated network should be removed in tearDown successfully
self.delete_network(isolated_network1, self.apiclient, True)
self.delete_network(isolated_network2, self.domainapiclient, True)
self.delete_network(vpc1_tier1, self.apiclient, True)
self.delete_vpc(self.apiclient, vpc1)
self.delete_network(vpc2_tier1, self.domainapiclient, True)
self.delete_vpc(self.domainapiclient, vpc2)

View File

@ -3143,7 +3143,7 @@ class Network:
networkofferingid=None, projectid=None,
subdomainaccess=None, zoneid=None,
gateway=None, netmask=None, vpcid=None, aclid=None, vlan=None,
externalid=None, bypassvlanoverlapcheck=None):
externalid=None, bypassvlanoverlapcheck=None, associatednetworkid=None):
"""Create Network for account"""
cmd = createNetwork.createNetworkCmd()
cmd.name = services["name"]
@ -3211,6 +3211,8 @@ class Network:
cmd.externalid = externalid
if bypassvlanoverlapcheck:
cmd.bypassvlanoverlapcheck = bypassvlanoverlapcheck
if associatednetworkid:
cmd.associatednetworkid = associatednetworkid
return Network(apiclient.createNetwork(cmd).__dict__)
def delete(self, apiclient):
@ -4731,14 +4733,15 @@ class PrivateGateway:
@classmethod
def create(cls, apiclient, gateway, ipaddress, netmask, vlan, vpcid,
physicalnetworkid=None, aclid=None, bypassvlanoverlapcheck=None):
physicalnetworkid=None, aclid=None, bypassvlanoverlapcheck=None, associatednetworkid=None):
"""Create private gateway"""
cmd = createPrivateGateway.createPrivateGatewayCmd()
cmd.gateway = gateway
cmd.ipaddress = ipaddress
cmd.netmask = netmask
cmd.vlan = vlan
if vlan:
cmd.vlan = vlan
cmd.vpcid = vpcid
if physicalnetworkid:
cmd.physicalnetworkid = physicalnetworkid
@ -4746,6 +4749,8 @@ class PrivateGateway:
cmd.aclid = aclid
if bypassvlanoverlapcheck:
cmd.bypassvlanoverlapcheck = bypassvlanoverlapcheck
if associatednetworkid:
cmd.associatednetworkid = associatednetworkid
return PrivateGateway(apiclient.createPrivateGateway(cmd).__dict__)
@ -5301,7 +5306,7 @@ class NIC:
"""Remove secondary Ip from NIC"""
cmd = removeIpFromNic.removeIpFromNicCmd()
cmd.id = ipaddressid
return (apiclient.addIpToNic(cmd))
return (apiclient.removeIpFromNic(cmd))
@classmethod
def list(cls, apiclient, **kwargs):
@ -5313,6 +5318,14 @@ class NIC:
cmd.listall = True
return (apiclient.listNics(cmd))
@classmethod
def updateIp(cls, apiclient, id, ipaddress=None):
"""Update Ip for NIC"""
cmd = updateVmNicIp.updateVmNicIpCmd()
cmd.nicid = id
if ipaddress:
cmd.ipaddress = ipaddress
return (apiclient.updateVmNicIp(cmd))
class SimulatorMock:
"""Manage simulator mock lifecycle"""
@ -5656,3 +5669,40 @@ class ProjectRolePermission:
cmd.projectid = projectid
[setattr(cmd, k, v) for k, v in list(kwargs.items())]
return (apiclient.listProjectRolePermissions(cmd))
class NetworkPermission:
"""Manage Network Permission"""
def __init__(self, items):
self.__dict__.update(items)
@classmethod
def create(cls, apiclient, **kwargs):
"""Creates network permissions"""
cmd = createNetworkPermissions.createNetworkPermissionsCmd()
[setattr(cmd, k, v) for k, v in list(kwargs.items())]
return (apiclient.createNetworkPermissions(cmd))
@classmethod
def remove(cls, apiclient, **kwargs):
"""Removes the network permissions"""
cmd = removeNetworkPermissions.removeNetworkPermissionsCmd()
[setattr(cmd, k, v) for k, v in list(kwargs.items())]
return (apiclient.removeNetworkPermissions(cmd))
@classmethod
def reset(cls, apiclient, **kwargs):
"""Updates the network permissions"""
cmd = resetNetworkPermissions.resetNetworkPermissionsCmd()
[setattr(cmd, k, v) for k, v in list(kwargs.items())]
return (apiclient.resetNetworkPermissions(cmd))
@classmethod
def list(cls, apiclient, **kwargs):
"""List all role permissions matching criteria"""
cmd = listNetworkPermissions.listNetworkPermissionsCmd()
[setattr(cmd, k, v) for k, v in list(kwargs.items())]
return (apiclient.listNetworkPermissions(cmd))

View File

@ -119,6 +119,7 @@
"label.action.delete.load.balancer": "Delete load balancer rule",
"label.action.delete.load.balancer.processing": "Deleting Load Balancer....",
"label.action.delete.network": "Delete Network",
"label.action.delete.network.permission": "Delete Network Permission",
"label.action.delete.network.processing": "Deleting Network....",
"label.action.delete.nexusvswitch": "Delete Nexus 1000v",
"label.action.delete.nic": "Remove NIC",
@ -250,6 +251,7 @@
"label.action.remove.host.processing": "Removing Host....",
"label.action.remove.vm": "Release VM",
"label.action.reserve.ip": "Reserve Public IP",
"label.action.reset.network.permissions": "Reset Network Permissions",
"label.action.reset.password": "Reset Password",
"label.action.reset.password.processing": "Resetting Password....",
"label.action.resize.volume": "Resize Volume",
@ -344,6 +346,7 @@
"label.add.network.acl.list": "Add Network ACL List",
"label.add.network.device": "Add Network Device",
"label.add.network.offering": "Add Network Offering",
"label.add.network.permission": "Add Network Permission",
"label.add.new.f5": "Add new F5",
"label.add.new.gateway": "Add new gateway",
"label.add.new.iso": "Add new ISO",
@ -439,6 +442,7 @@
"label.all": "All",
"label.all.zone": "All Zones",
"label.allocated": "Allocated",
"label.allocatedonly": "Allocated",
"label.allocatediops": "IOPS Allocated",
"label.allocationstate": "Allocation State",
"label.allow": "Allow",
@ -1045,6 +1049,7 @@
"label.guestnetworkname": "Network Name",
"label.guestosid": "OS Type",
"label.gueststartip": "Guest start IP",
"label.guest.vlan": "Guest VLAN",
"label.guestvlanrange": "VLAN Range(s)",
"label.guestvmcidr": "CIDR",
"label.ha": "HA",
@ -1516,6 +1521,7 @@
"label.network.offering.display.text": "Network Offering Display Text",
"label.network.offering.name": "Network Offering Name",
"label.network.offerings": "Network Offerings",
"label.network.permissions": "Network Permissions",
"label.network.selection": "Network Selection",
"label.network.service.providers": "Network Service Providers",
"label.networkcidr": "Network CIDR",
@ -1665,6 +1671,7 @@
"label.physical.network.id": "Physical network ID",
"label.physical.network.name": "Physical network name",
"label.physicalnetworkid": "Physical Network",
"label.physicalnetworkname": "Physical Network Name",
"label.physicalsize": "Physical Size",
"label.ping.cifs.password": "PING CIFS password",
"label.ping.cifs.username": "PING CIFS username",
@ -2192,6 +2199,7 @@
"label.tag.value": "Tag Value",
"label.tagged": "Tagged",
"label.tags": "Tags",
"label.taken": "Taken",
"label.target.iqn": "Target IQN",
"label.tariffactions": "Actions",
"label.tariffvalue": "Tariff Value",
@ -2773,11 +2781,13 @@
"message.confirm.remove.ip.range": "Please confirm that you would like to remove this IP range.",
"message.confirm.remove.load.balancer": "Please confirm you want to remove VM from load balancer",
"message.confirm.remove.network.offering": "Are you sure you want to remove this network offering?",
"message.confirm.remove.network.permission": "Are you sure you want to remove this network permission?",
"message.confirm.remove.selected.alerts": "Please confirm you would like to remove the selected alerts",
"message.confirm.remove.selected.events": "Please confirm you would like to remove the selected events",
"message.confirm.remove.vmware.datacenter": "Please confirm you want to remove VMware datacenter",
"message.confirm.remove.vpc.offering": "Are you sure you want to remove this VPC offering?",
"message.confirm.replace.acl.new.one": "Do you want to replace the ACL with a new one?",
"message.confirm.reset.network.permissions": "Are you sure you want to reset this network permissions?",
"message.confirm.scale.up.router.vm": "Do you really want to scale up the Router VM ?",
"message.confirm.scale.up.system.vm": "Do you really want to scale up the system VM ?",
"message.confirm.shutdown.provider": "Please confirm that you would like to shutdown this provider",
@ -3288,6 +3298,7 @@
"message.setup.physical.network.during.zone.creation": "When adding a zone, you need to set up one or more physical networks. Each network corresponds to a NIC on the hypervisor. Each physical network can carry one or more types of traffic, with certain restrictions on how they may be combined. Add or remove one or more traffic types onto each physical network.",
"message.setup.physical.network.during.zone.creation.basic": "When adding a basic zone, you can set up one physical network, which corresponds to a NIC on the hypervisor. The network carries several types of traffic.<br/><br/>You may also <strong>add</strong> other traffic types onto the physical network.",
"message.setup.successful": "Cloud setup successful!",
"message.shared.network.offering.warning": "Domain admins and regular users can only create Shared networks from network offering with specifyvlan=false. Please contact admin to create a network offering if this list is empty.",
"message.specify.tag.key": "Please specify a tag key",
"message.specify.tag.key.value": "Please specify a tag key and value",
"message.specify.tag.value": "Please specify a tag value",
@ -3307,6 +3318,7 @@
"message.success.add.kuberversion": "Successfully added Kubernetes version",
"message.success.add.network": "Successfully added network",
"message.success.add.network.acl": "Successfully added Network ACL List",
"message.success.add.network.permissions": "Successfully added Network Permissions",
"message.success.add.port.forward": "Successfully added new Port Forwarding rule",
"message.success.add.private.gateway": "Successfully added Private Gateway",
"message.success.add.rule": "Successfully added new rule",
@ -3362,11 +3374,13 @@
"message.success.remove.instance.rule": "Successfully removed instance from rule",
"message.success.remove.ip": "Successfully removed IP",
"message.success.remove.iprange": "Successfully removed IP Range",
"message.success.remove.network.permissions": "Successfully removed Network Permissions",
"message.success.remove.nic": "Successfully removed",
"message.success.remove.port.forward": "Successfully removed Port Forwarding rule",
"message.success.remove.rule": "Successfully deleted rule",
"message.success.remove.secondary.ipaddress": "Successfully removed secondary IP Address",
"message.success.remove.sticky.policy": "Successfully removed sticky policy",
"message.success.reset.network.permissions": "Successfully reset Network Permissions",
"message.success.resize.volume": "Successfully resized volume",
"message.success.scale.kubernetes": "Successfully scaled Kubernetes cluster",
"message.success.unmanage.instance": "Successfully unmanaged instance",

View File

@ -385,7 +385,7 @@
<div class="resource-detail-item__label">{{ $t('label.associatednetwork') }}</div>
<div class="resource-detail-item__details">
<wifi-outlined />
<router-link :to="{ path: '/guestnetwork/' + resource.associatednetworkid }">{{ resource.associatednetworkname || resource.associatednetworkid }} </router-link>
<router-link :to="{ path: '/guestnetwork/' + resource.associatednetworkid }">{{ resource.associatednetworkname || resource.associatednetwork || resource.associatednetworkid }} </router-link>
</div>
</div>
<div class="resource-detail-item" v-if="resource.sourceipaddressnetworkid">

View File

@ -195,6 +195,11 @@
<template #agentstate="{ text }">
<status :text="text ? text : ''" displayText />
</template>
<template #vlan="{ text, record }">
<a href="javascript:;">
<router-link v-if="$route.path === '/guestvlans'" :to="{ path: '/guestvlans/' + record.id }">{{ text }}</router-link>
</a>
</template>
<template #guestnetworkname="{ text, record }">
<router-link :to="{ path: '/guestnetwork/' + record.guestnetworkid }">{{ text }}</router-link>
</template>

View File

@ -250,7 +250,7 @@ export default {
if (item === 'clusterid' && !('listClusters' in this.$store.getters.apis)) {
return true
}
if (['zoneid', 'domainid', 'state', 'level', 'clusterid', 'podid', 'entitytype'].includes(item)) {
if (['zoneid', 'domainid', 'state', 'level', 'clusterid', 'podid', 'entitytype', 'type'].includes(item)) {
type = 'list'
} else if (item === 'tags') {
type = 'tag'
@ -271,6 +271,15 @@ export default {
let podIndex = -1
let clusterIndex = -1
if (arrayField.includes('type')) {
if (this.$route.path === '/guestnetwork' || this.$route.path.includes('/guestnetwork/')) {
const typeIndex = this.fields.findIndex(item => item.name === 'type')
this.fields[typeIndex].loading = true
this.fields[typeIndex].opts = this.fetchGuestNetworkTypes()
this.fields[typeIndex].loading = false
}
}
if (arrayField.includes('state')) {
const stateIndex = this.fields.findIndex(item => item.name === 'state')
this.fields[stateIndex].loading = true
@ -431,6 +440,24 @@ export default {
})
})
},
fetchGuestNetworkTypes () {
const types = []
if (this.apiName.indexOf('listNetworks') > -1) {
types.push({
id: 'Isolated',
name: 'label.isolated'
})
types.push({
id: 'Shared',
name: 'label.shared'
})
types.push({
id: 'L2',
name: 'label.l2'
})
}
return types
},
fetchState () {
const state = []
if (this.apiName.indexOf('listVolumes') > -1) {

View File

@ -39,14 +39,14 @@ export default {
return fields
},
details: () => {
var fields = ['name', 'id', 'description', 'type', 'traffictype', 'vpcid', 'vlan', 'broadcasturi', 'cidr', 'ip6cidr', 'netmask', 'gateway', 'aclname', 'ispersistent', 'restartrequired', 'reservediprange', 'redundantrouter', 'networkdomain', 'egressdefaultpolicy', 'zonename', 'account', 'domain']
var fields = ['name', 'id', 'description', 'type', 'traffictype', 'vpcid', 'vlan', 'broadcasturi', 'cidr', 'ip6cidr', 'netmask', 'gateway', 'aclname', 'ispersistent', 'restartrequired', 'reservediprange', 'redundantrouter', 'networkdomain', 'egressdefaultpolicy', 'zonename', 'account', 'domain', 'associatednetwork', 'associatednetworkid']
if (!isAdmin()) {
fields = fields.filter(function (e) { return e !== 'broadcasturi' })
}
return fields
},
filters: ['all', 'isolated', 'shared', 'l2'],
searchFilters: ['keyword', 'zoneid', 'domainid', 'account', 'tags'],
filters: ['all', 'account', 'domain', 'shared'],
searchFilters: ['keyword', 'zoneid', 'domainid', 'account', 'type', 'tags'],
related: [{
name: 'vm',
title: 'label.instances',
@ -71,6 +71,10 @@ export default {
name: 'guest.ip.range',
component: shallowRef(defineAsyncComponent(() => import('@/views/network/GuestIpRanges.vue'))),
show: (record) => { return 'listVlanIpRanges' in store.getters.apis && (record.type === 'Shared' || (record.service && record.service.filter(x => x.name === 'SourceNat').count === 0)) }
}, {
name: 'network.permissions',
component: shallowRef(defineAsyncComponent(() => import('@/views/network/NetworkPermissions.vue'))),
show: (record, route, user) => { return 'listNetworkPermissions' in store.getters.apis && record.acltype === 'Account' && !('vpcid' in record) && (['Admin', 'DomainAdmin'].includes(user.roletype) || record.account === user.account) }
},
{
name: 'comments',
@ -372,7 +376,7 @@ export default {
hidden: true,
permission: ['listPrivateGateways'],
columns: ['ipaddress', 'state', 'gateway', 'netmask', 'account'],
details: ['ipaddress', 'gateway', 'netmask', 'vlan', 'sourcenatsupported', 'aclname', 'account', 'domain', 'zone'],
details: ['ipaddress', 'gateway', 'netmask', 'vlan', 'sourcenatsupported', 'aclname', 'account', 'domain', 'zone', 'associatednetwork', 'associatednetworkid'],
tabs: [{
name: 'details',
component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue')))
@ -707,6 +711,31 @@ export default {
groupMap: (selection) => { return selection.map(x => { return { id: x } }) }
}
]
},
{
name: 'guestvlans',
title: 'label.guest.vlan',
icon: 'folder-outlined',
permission: ['listGuestVlans'],
resourceType: 'GuestVlan',
filters: ['allocatedonly', 'all'],
columns: ['vlan', 'zonename', 'physicalnetworkname', 'allocationstate', 'taken', 'domain', 'account', 'project'],
details: ['vlan', 'zonename', 'physicalnetworkname', 'allocationstate', 'taken', 'domain', 'account', 'project', 'isdedicated'],
searchFilters: ['zoneid'],
tabs: [{
name: 'details',
component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue')))
}, {
name: 'guest.networks',
component: shallowRef(defineAsyncComponent(() => import('@/views/network/GuestVlanNetworksTab.vue'))),
show: (record) => { return (record.allocationstate === 'Allocated') }
}],
show: () => {
if (!store.getters.zones || store.getters.zones.length === 0) {
return false
}
return true
}
}
]
}

View File

@ -56,7 +56,7 @@
:value="$route.query.filter || (projectView && $route.name === 'vm' ||
['Admin', 'DomainAdmin'].includes($store.getters.userInfo.roletype) && ['vm', 'iso', 'template'].includes($route.name)
? 'all' : ['publicip'].includes($route.name)
? 'allocated': ['guestnetwork'].includes($route.name) ? 'all' : 'self')"
? 'allocated' : ['guestnetwork', 'guestvlans'].includes($route.name) ? 'all' : 'self')"
style="min-width: 100px; margin-left: 10px"
@change="changeFilter"
showSearch
@ -1497,9 +1497,9 @@ export default {
query.isofilter = filter
} else if (this.$route.name === 'guestnetwork') {
if (filter === 'all') {
delete query.type
delete query.networkfilter
} else {
query.type = filter
query.networkfilter = filter
}
} else if (this.$route.name === 'publicip') {
query.state = filter
@ -1512,6 +1512,12 @@ export default {
}
} else if (this.$route.name === 'comment') {
query.annotationfilter = filter
} else if (this.$route.name === 'guestvlans') {
if (filter === 'all') {
query.allocatedonly = 'false'
} else if (filter === 'allocatedonly') {
query.allocatedonly = 'true'
}
}
query.filter = filter
query.page = '1'

View File

@ -34,7 +34,7 @@
@refresh-data="refreshParent"
@refresh="handleRefresh"/>
</a-tab-pane>
<a-tab-pane :tab="$t('label.shared')" key="3" v-if="isAdmin()">
<a-tab-pane :tab="$t('label.shared')" key="3">
<CreateSharedNetworkForm
:loading="loading"
:resource="resource"
@ -48,7 +48,6 @@
<script>
import { api } from '@/api'
import { isAdmin } from '@/role'
import CreateIsolatedNetworkForm from '@/views/network/CreateIsolatedNetworkForm'
import CreateL2NetworkForm from '@/views/network/CreateL2NetworkForm'
import CreateSharedNetworkForm from '@/views/network/CreateSharedNetworkForm'
@ -108,9 +107,6 @@ export default {
this.loading = false
})
},
isAdmin () {
return isAdmin()
},
handleRefresh () {
},
refreshParent () {

View File

@ -0,0 +1,247 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
<template>
<a-spin :spinning="loading">
<div class="form-layout" v-ctrl-enter="handleSubmit">
<div class="form">
<a-form
:ref="formRef"
:model="form"
:rules="rules"
@finish="handleSubmit"
layout="vertical">
<a-form-item v-if="isAdminOrDomainAdmin()" name="accountids" ref="accountids">
<template #label>
<tooltip-label :title="$t('label.account')" :tooltip="apiParams.accountids.description"/>
</template>
<a-select
v-model:value="form.accountids"
mode="multiple"
:loading="accountLoading"
:placeholder="apiParams.accountids.description"
showSearch
optionFilterProp="children"
:filterOption="(input, option) => {
return option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
}" >
<a-select-option v-for="(opt, optIndex) in accounts" :key="optIndex" :label="opt.name || opt.description">
<span>
<resource-icon v-if="opt.icon" :image="opt.icon.base64image" size="1x" style="margin-right: 5px"/>
<global-outlined style="margin-right: 5px" />
{{ opt.name || opt.description }}
</span>
</a-select-option>
</a-select>
</a-form-item>
<a-form-item v-if="isAdminOrDomainAdmin()" name="projectids" ref="projectids">
<template #label>
<tooltip-label :title="$t('label.project')" :tooltip="apiParams.projectids.description"/>
</template>
<a-select
v-model:value="form.projectids"
mode="multiple"
:loading="projectLoading"
:placeholder="apiParams.projectids.description"
showSearch
optionFilterProp="children"
:filterOption="(input, option) => {
return option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
}" >
<a-select-option v-for="(opt, optIndex) in projects" :key="optIndex" :label="opt.name || opt.description">
<span>
<resource-icon v-if="opt.icon" :image="opt.icon.base64image" size="1x" style="margin-right: 5px"/>
<global-outlined style="margin-right: 5px" />
{{ opt.name || opt.description }}
</span>
</a-select-option>
</a-select>
</a-form-item>
<a-form-item v-if="!isAdminOrDomainAdmin()">
<template #label>
<tooltip-label :title="$t('label.accounts')" :tooltip="apiParams.accounts.description"/>
</template>
<a-input
v-model:value="form.accounts"
:placeholder="apiParams.accounts.description"
v-focus="true" />
</a-form-item>
<div :span="24" class="action-button">
<a-button
:loading="loading"
@click="closeAction">
{{ this.$t('label.cancel') }}
</a-button>
<a-button
:loading="loading"
type="primary"
ref="submit"
@click="handleSubmit">
{{ this.$t('label.ok') }}
</a-button>
</div>
</a-form>
</div>
</div>
</a-spin>
</template>
<script>
import { api } from '@/api'
import { isAdminOrDomainAdmin } from '@/role'
import { ref, reactive, toRaw } from 'vue'
import ResourceIcon from '@/components/view/ResourceIcon'
import TooltipLabel from '@/components/widgets/TooltipLabel'
export default {
name: 'CreateNetworkPermissions',
components: {
TooltipLabel,
ResourceIcon
},
props: {
resource: {
type: Object,
required: true
}
},
data () {
return {
loading: false,
accountLoading: false,
projectLoading: false,
accounts: [],
projects: []
}
},
created () {
this.formRef = ref()
this.form = reactive({})
this.apiParams = this.$getApiParams('createNetworkPermissions')
this.fetchData()
},
methods: {
isAdminOrDomainAdmin () {
return isAdminOrDomainAdmin()
},
async fetchData () {
this.fetchAccountData()
this.fetchProjectData()
},
fetchAccountData () {
this.accounts = []
const params = {}
params.showicon = true
params.details = 'min'
params.domainid = this.resource.domainid
this.accountLoading = true
api('listAccounts', params).then(json => {
const listaccounts = json.listaccountsresponse.account || []
this.accounts = listaccounts
}).finally(() => {
this.accountLoading = false
})
},
fetchProjectData () {
this.projects = []
const params = {}
params.listall = true
params.showicon = true
params.details = 'min'
params.domainid = this.resource.domainid
this.projectLoading = true
api('listProjects', params).then(json => {
const listProjects = json.listprojectsresponse.project || []
this.projects = listProjects
}).finally(() => {
this.projectLoading = false
})
},
handleSubmit (e) {
e.preventDefault()
if (this.loading) return
this.formRef.value.validate().then(() => {
const values = toRaw(this.form)
const params = {}
params.networkid = this.resource.id
var accountIndexes = values.accountids
var accountId = null
if (accountIndexes && accountIndexes.length > 0) {
var accountIds = []
for (var i = 0; i < accountIndexes.length; i++) {
accountIds = accountIds.concat(this.accounts[accountIndexes[i]].id)
}
accountId = accountIds.join(',')
}
if (accountId) {
params.accountids = accountId
}
var projectIndexes = values.projectids
var projectId = null
if (projectIndexes && projectIndexes.length > 0) {
var projectIds = []
for (var j = 0; j < projectIndexes.length; j++) {
projectIds = projectIds.concat(this.projects[projectIndexes[j]].id)
}
projectId = projectIds.join(',')
}
if (projectId) {
params.projectids = projectId
}
if (values.accounts && values.accounts.length > 0) {
params.accounts = values.accounts
}
this.loading = true
api('createNetworkPermissions', params)
.then(() => {
this.$notification.success({
message: this.$t('message.success.add.network.permissions')
})
this.closeAction()
this.$emit('refresh-data')
}).catch(error => {
this.$notification.error({
message: `${this.$t('label.error')} ${error.response.status}`,
description: error.response.data.createnetworkpermissionsresponse.errortext || error.response.data.errorresponse.errortext,
duration: 0
})
}).finally(() => {
this.loading = false
})
}).catch(error => {
this.formRef.value.scrollToField(error.errorFields[0].name)
})
},
closeAction () {
this.$emit('close-action')
}
}
}
</script>
<style lang="less" scoped>
.form-layout {
width: 60vw;
@media (min-width: 500px) {
width: 450px;
}
}
</style>

View File

@ -66,7 +66,7 @@
</a-select-option>
</a-select>
</a-form-item>
<a-form-item v-if="isObjectEmpty(zone)" name="physicalnetworkid" ref="physicalnetworkid">
<a-form-item v-if="isObjectEmpty(zone) && isAdmin()" name="physicalnetworkid" ref="physicalnetworkid">
<template #label>
<tooltip-label :title="$t('label.physicalnetworkid')" :tooltip="apiParams.physicalnetworkid.description"/>
</template>
@ -75,7 +75,7 @@
showSearch
optionFilterProp="label"
:filterOption="(input, option) => {
return option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
}"
:loading="formPhysicalNetworkLoading"
:placeholder="apiParams.physicalnetworkid.description"
@ -85,7 +85,7 @@
</a-select-option>
</a-select>
</a-form-item>
<a-form-item name="vlanid" ref="vlanid">
<a-form-item v-if="!this.isObjectEmpty(this.selectedNetworkOffering) && this.selectedNetworkOffering.specifyvlan && isAdmin()" name="vlanid" ref="vlanid">
<template #label>
<tooltip-label :title="$t('label.vlan')" :tooltip="apiParams.vlan.description"/>
</template>
@ -93,14 +93,14 @@
v-model:value="form.vlanid"
:placeholder="apiParams.vlan.description"/>
</a-form-item>
<a-form-item name="bypassvlanoverlapcheck" ref="bypassvlanoverlapcheck">
<a-form-item name="bypassvlanoverlapcheck" ref="bypassvlanoverlapcheck" v-if="isAdmin()">
<template #label>
<tooltip-label :title="$t('label.bypassvlanoverlapcheck')" :tooltip="apiParams.bypassvlanoverlapcheck.description"/>
</template>
<a-switch v-model:checked="form.bypassvlanoverlapcheck" />
</a-form-item>
<a-form-item
v-if="!isObjectEmpty(selectedNetworkOffering) && selectedNetworkOffering.specifyvlan"
v-if="!isObjectEmpty(selectedNetworkOffering) && selectedNetworkOffering.specifyvlan && isAdmin()"
name="isolatedpvlantype"
ref="isolatedpvlantype">
<template #label>
@ -136,10 +136,10 @@
v-model:value="form.scope"
buttonStyle="solid"
@change="selected => { handleScopeTypeChange(selected.target.value) }">
<a-radio-button value="all">
<a-radio-button value="all" v-if="isAdmin()">
{{ $t('label.all') }}
</a-radio-button>
<a-radio-button value="domain" v-if="!parseBooleanValueForKey(selectedZone, 'securitygroupsenabled')">
<a-radio-button value="domain" v-if="!parseBooleanValueForKey(selectedZone, 'securitygroupsenabled') && isAdminOrDomainAdmin()">
{{ $t('label.domain') }}
</a-radio-button>
<a-radio-button value="account" v-if="!parseBooleanValueForKey(selectedZone, 'securitygroupsenabled')">
@ -150,7 +150,7 @@
</a-radio-button>
</a-radio-group>
</a-form-item>
<a-form-item v-if="scopeType !== 'all'" name="domainid" ref="domainid">
<a-form-item v-if="scopeType !== 'all' && isAdminOrDomainAdmin()" name="domainid" ref="domainid">
<template #label>
<tooltip-label :title="$t('label.domainid')" :tooltip="apiParams.domainid.description"/>
</template>
@ -164,32 +164,47 @@
:loading="domainLoading"
:placeholder="apiParams.domainid.description"
@change="val => { handleDomainChange(domains[val]) }">
<a-select-option v-for="(opt, optIndex) in domains" :key="optIndex" :label="opt.path || opt.name || opt.description">
<a-select-option v-for="(opt, optIndex) in domains" :key="optIndex">
<span>
<resource-icon v-if="opt && opt.icon" :image="opt.icon.base64image" size="1x" style="margin-right: 5px"/>
<block-outlined v-else-if="optIndex !== 0" style="margin-right: 5px" />
<block-outlined v-else style="margin-right: 5px" />
{{ opt.path || opt.name || opt.description }}
</span>
</a-select-option>
</a-select>
</a-form-item>
<a-form-item v-if="scopeType === 'domain'" name="subdomainaccess" ref="subdomainaccess">
<a-form-item v-if="scopeType === 'domain' && isAdminOrDomainAdmin()" name="subdomainaccess" ref="subdomainaccess">
<template #label>
<tooltip-label :title="$t('label.subdomainaccess')" :tooltip="apiParams.subdomainaccess.description"/>
</template>
<a-switch v-model:checked="form.subdomainaccess" />
</a-form-item>
<a-form-item v-if="scopeType === 'account'" name="account" ref="account">
<a-form-item v-if="scopeType === 'account' && isAdminOrDomainAdmin()" name="account" ref="account">
<template #label>
<tooltip-label :title="$t('label.account')" :tooltip="apiParams.account.description"/>
</template>
<a-input
<a-select
v-model:value="form.account"
:placeholder="apiParams.account.description"/>
showSearch
optionFilterProp="label"
:filterOption="(input, option) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
}"
:loading="accountLoading"
:placeholder="apiParams.account.description"
@change="val => { handleAccountChange(accounts[val]) }">
<a-select-option v-for="(opt, optIndex) in accounts" :key="optIndex">
<span>
<resource-icon v-if="opt && opt.icon" :image="opt.icon.base64image" size="1x" style="margin-right: 5px"/>
<user-outlined v-else style="margin-right: 5px" />
{{ opt.name || opt.description }}
</span>
</a-select-option>
</a-select>
</a-form-item>
<a-form-item v-if="scopeType === 'project'" name="projectid" ref="projectid">
<template #label>
<tooltip-label :title="$t('label.projectid')" :tooltip="apiParams.projectid.description"/>
<tooltip-label :title="$t('label.project')" :tooltip="apiParams.projectid.description"/>
</template>
<a-select
v-model:value="form.projectid"
@ -201,12 +216,8 @@
:loading="projectLoading"
:placeholder="apiParams.projectid.description"
@change="val => { handleProjectChange(projects[val]) }">
<a-select-option v-for="(opt, optIndex) in projects" :key="optIndex" :label="opt.name || opt.description">
<span>
<resource-icon v-if="opt && opt.icon" :image="opt.icon.base64image" size="1x" style="margin-right: 5px"/>
<project-outlined v-else-if="optIndex !== 0" style="margin-right: 5px" />
{{ opt.name || opt.description }}
</span>
<a-select-option v-for="(opt, optIndex) in projects" :key="optIndex">
{{ opt.name || opt.description }}
</a-select-option>
</a-select>
</a-form-item>
@ -219,7 +230,7 @@
showSearch
optionFilterProp="label"
:filterOption="(input, option) => {
return option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
}"
:loading="networkOfferingLoading"
:placeholder="apiParams.networkofferingid.description"
@ -228,6 +239,31 @@
{{ opt.displaytext || opt.name || opt.description }}
</a-select-option>
</a-select>
<a-alert type="warning" :loading="networkOfferingLoading" v-if="networkOfferingWarning">
<template #message>{{ $t('message.shared.network.offering.warning') }}</template>
</a-alert>
</a-form-item>
<a-form-item v-if="!isObjectEmpty(selectedNetworkOffering) && !selectedNetworkOffering.specifyvlan" name="associatednetworkid" ref="associatednetworkid">
<template #label>
<tooltip-label :title="$t('label.associatednetwork')" :tooltip="apiParams.associatednetworkid.description"/>
</template>
<a-select
showSearch
optionFilterProp="label"
:filterOption="(input, option) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
}"
:loading="networkLoading"
:placeholder="this.$t('label.associatednetwork')"
@change="val => { this.handleNetworkChange(this.networks[val]) }">
<a-select-option v-for="(opt, optIndex) in this.networks" :key="optIndex" :label="opt.name || opt.description">
<span>
<resource-icon v-if="opt && opt.icon" :image="opt.icon.base64image" size="1x" style="margin-right: 5px"/>
<apartment-outlined v-else style="margin-right: 5px" />
{{ opt.name || opt.description }}
</span>
</a-select-option>
</a-select>
</a-form-item>
<a-form-item name="ip4gateway" ref="ip4gateway">
<template #label>
@ -338,6 +374,7 @@
<script>
import { ref, reactive, toRaw } from 'vue'
import { api } from '@/api'
import { isAdmin, isAdminOrDomainAdmin } from '@/role'
import { mixinForm } from '@/utils/mixin'
import ResourceIcon from '@/components/view/ResourceIcon'
import TooltipLabel from '@/components/widgets/TooltipLabel'
@ -358,10 +395,6 @@ export default {
type: Object,
default: null
},
physicalNetworks: {
type: Array,
default: null
},
resource: {
type: Object,
default: () => { return {} }
@ -382,7 +415,14 @@ export default {
selectedDomain: {},
networkOfferings: [],
networkOfferingLoading: false,
networkOfferingWarning: false,
selectedNetworkOffering: {},
networks: [],
networkLoading: false,
selectedNetwork: {},
accounts: [],
accountLoading: false,
selectedAccount: {},
projects: [],
projectLoading: false,
selectedProject: {},
@ -408,8 +448,15 @@ export default {
methods: {
initForm () {
this.formRef = ref()
if (isAdmin()) {
this.scopeType = 'all'
} else if (isAdminOrDomainAdmin()) {
this.scopeType = 'domain'
} else {
this.scopeType = 'account'
}
this.form = reactive({
scope: 'all',
scope: this.scopeType,
isolatedpvlantype: 'none'
})
this.rules = reactive({
@ -418,8 +465,9 @@ export default {
zoneid: [{ type: 'number', required: true, message: this.$t('message.error.select') }],
vlanid: [{ required: true, message: this.$t('message.please.enter.value') }],
networkofferingid: [{ type: 'number', required: true, message: this.$t('message.error.select') }],
domainid: [{ required: true, message: this.$t('message.error.select') }],
projectid: [{ required: true, message: this.$t('message.error.select') }]
domainid: [{ type: 'number', required: true, message: this.$t('message.error.select') }],
account: [{ type: 'number', required: true, message: this.$t('message.error.select') }],
projectid: [{ type: 'number', required: true, message: this.$t('message.error.select') }]
})
},
fetchData () {
@ -428,6 +476,15 @@ export default {
} else {
this.fetchNetworkOfferingData()
}
if (this.scopeType !== 'all') {
this.handleScopeTypeChange(this.scopeType)
}
},
isAdmin () {
return isAdmin()
},
isAdminOrDomainAdmin () {
return isAdminOrDomainAdmin()
},
isObjectEmpty (obj) {
return !(obj !== null && obj !== undefined && Object.keys(obj).length > 0 && obj.constructor === Object)
@ -478,43 +535,42 @@ export default {
},
handleZoneChange (zone) {
this.selectedZone = zone
this.fetchPhysicalNetworkData()
if (isAdmin()) {
this.fetchPhysicalNetworkData()
} else {
this.fetchNetworkOfferingData()
}
},
fetchPhysicalNetworkData () {
this.formSelectedPhysicalNetwork = {}
this.formPhysicalNetworks = []
if (this.physicalNetworks != null) {
this.formPhysicalNetworks = this.physicalNetworks
this.selectFirstPhysicalNetwork()
} else {
if (this.selectedZone === null || this.selectedZone === undefined) {
return
}
const promises = []
const params = {
zoneid: this.selectedZone.id
}
this.formPhysicalNetworkLoading = true
api('listPhysicalNetworks', params).then(json => {
var networks = json.listphysicalnetworksresponse.physicalnetwork
if (this.arrayHasItems(networks)) {
for (const network of networks) {
promises.push(this.addPhysicalNetworkForGuestTrafficType(network))
}
} else {
this.formPhysicalNetworkLoading = false
}
}).finally(() => {
if (this.arrayHasItems(promises)) {
Promise.all(promises).catch(error => {
this.$notifyError(error)
}).finally(() => {
this.formPhysicalNetworkLoading = false
this.selectFirstPhysicalNetwork()
})
}
})
if (this.selectedZone === null || this.selectedZone === undefined) {
return
}
const promises = []
const params = {
zoneid: this.selectedZone.id
}
this.formPhysicalNetworkLoading = true
api('listPhysicalNetworks', params).then(json => {
var networks = json.listphysicalnetworksresponse.physicalnetwork
if (this.arrayHasItems(networks)) {
for (const network of networks) {
promises.push(this.addPhysicalNetworkForGuestTrafficType(network))
}
} else {
this.formPhysicalNetworkLoading = false
}
}).finally(() => {
if (this.arrayHasItems(promises)) {
Promise.all(promises).catch(error => {
this.$notifyError(error)
}).finally(() => {
this.formPhysicalNetworkLoading = false
this.selectFirstPhysicalNetwork()
})
}
})
},
selectFirstPhysicalNetwork () {
if (this.arrayHasItems(this.formPhysicalNetworks)) {
@ -556,14 +612,29 @@ export default {
}
case 'project':
{
this.fetchDomainData()
this.fetchProjectData()
this.fetchNetworkOfferingData()
if (isAdminOrDomainAdmin()) {
this.fetchDomainData()
} else {
this.fetchProjectData()
}
break
}
case 'account':
{
if (isAdminOrDomainAdmin()) {
this.fetchDomainData()
} else {
this.fetchNetworkOfferingData()
}
break
}
default:
{
this.fetchNetworkOfferingData()
if (isAdminOrDomainAdmin()) {
this.fetchDomainData()
} else {
this.fetchNetworkOfferingData()
}
}
}
},
@ -576,6 +647,9 @@ export default {
zoneid: this.selectedZone.id,
state: 'Enabled'
}
if (!isAdmin()) {
params.specifyvlan = false
}
if (!this.isObjectEmpty(this.formSelectedPhysicalNetwork) &&
this.formSelectedPhysicalNetwork.tags &&
this.formSelectedPhysicalNetwork.tags.length > 0) {
@ -583,25 +657,25 @@ export default {
}
// Network tab in Guest Traffic Type in Infrastructure menu is only available when it's under Advanced zone.
// zone dropdown in add guest network dialog includes only Advanced zones.
if (this.scopeType === 'all' || this.scopeType === 'domain') {
params.guestiptype = 'Shared'
if (this.scopeType === 'domain') {
params.domainid = this.selectedDomain.id
}
params.guestiptype = 'Shared'
if (this.scopeType === 'domain') {
params.domainid = this.selectedDomain.id
}
this.handleNetworkOfferingChange(null)
this.networkOfferings = []
api('listNetworkOfferings', params).then(json => {
this.networkOfferings = json.listnetworkofferingsresponse.networkoffering
this.handleNetworkOfferingChange(this.networkOfferings[0])
this.networkOfferings = json.listnetworkofferingsresponse.networkoffering || []
}).catch(error => {
this.$notifyError(error)
}).finally(() => {
this.networkOfferingLoading = false
if (this.arrayHasItems(this.networkOfferings)) {
this.form.networkofferingid = 0
this.handleNetworkOfferingChange(this.networkOfferings[0])
this.networkOfferingWarning = false
} else {
this.form.networkofferingid = null
this.networkOfferingWarning = true
}
})
},
@ -609,8 +683,71 @@ export default {
this.selectedNetworkOffering = networkOffering
if (networkOffering) {
this.networkServiceProviderMap(this.selectedNetworkOffering.id)
if (!networkOffering.specifyvlan) {
this.fetchNetworkData()
}
}
},
fetchNetworkData () {
if (this.isObjectEmpty(this.selectedZone)) {
return
}
if (this.isObjectEmpty(this.selectedNetworkOffering) || this.selectedNetworkOffering.specifyvlan) {
return
}
if (this.isObjectEmpty(this.selectedProject) && this.scopeType === 'project') {
return
}
this.networkLoading = true
var params = {
zoneid: this.selectedZone.id,
networkfilter: 'Account'
}
if (this.formSelectedPhysicalNetwork) {
params.physicalnetworkid = this.formSelectedPhysicalNetwork.id
}
switch (this.scopeType) {
case 'domain':
{
params.domainid = this.selectedDomain.id
params.ignoreproject = true
break
}
case 'project':
{
params.domainid = this.selectedProject.domainid
params.projectid = this.selectedProject.id
break
}
case 'account':
{
params.domainid = this.selectedAccount.domainid
params.account = this.selectedAccount.name
params.ignoreproject = true
break
}
default:
{
}
}
this.handleNetworkChange(null)
this.networks = []
api('listNetworks', params).then(json => {
var networks = json.listnetworksresponse.network || []
for (const network of networks) {
if (network.type === 'Isolated' || network.type === 'L2') {
this.networks.push(network)
}
}
}).catch(error => {
this.$notifyError(error)
}).finally(() => {
this.networkLoading = false
})
},
handleNetworkChange (selectedNetwork) {
this.selectedNetwork = selectedNetwork
},
networkServiceProviderMap (id) {
api('listNetworkOfferings', { id: id }).then(json => {
var networkOffering = json.listnetworkofferingsresponse.networkoffering[0]
@ -630,9 +767,10 @@ export default {
})
},
fetchDomainData () {
this.networkOfferingWarning = false
const params = {}
if (!this.isObjectEmpty(this.selectedZone) && this.selectedZone.domainid != null) {
params.id = this.selectedZone.id
params.id = this.selectedZone.domainid
params.isrecursive = true
} else {
params.listall = true
@ -640,40 +778,86 @@ export default {
params.showicon = true
this.domainLoading = true
api('listDomains', params).then(json => {
const listDomains = json.listdomainsresponse.domain
this.domains = this.domains.concat(listDomains)
const listDomains = json.listdomainsresponse.domain || []
this.domains = listDomains
}).finally(() => {
this.domainLoading = false
this.form.domainid = 0
this.handleDomainChange(this.domains[0])
if (this.arrayHasItems(this.domains) && this.scopeType !== 'all') {
this.form.domainid = 0
this.handleDomainChange(this.domains[0])
}
})
},
handleDomainChange (domain) {
this.selectedDomain = domain
if (!this.isObjectEmpty(domain)) {
if (this.scopeType === 'domain') {
this.fetchNetworkOfferingData()
} else if (this.scopeType === 'account') {
this.fetchAccountData()
} else if (this.scopeType === 'project') {
this.fetchProjectData()
}
}
},
fetchAccountData () {
this.networkOfferingWarning = false
this.accounts = []
const params = {}
params.showicon = true
params.details = 'min'
if (this.selectedDomain) {
params.domainid = this.selectedDomain.id
}
this.accountLoading = true
this.handleAccountChange(null)
api('listAccounts', params).then(json => {
this.accounts = json.listaccountsresponse.account || []
}).finally(() => {
this.accountLoading = false
if (this.arrayHasItems(this.accounts) && this.scopeType === 'account') {
this.form.account = 0
this.handleAccountChange(this.accounts[0])
} else {
this.form.account = null
}
})
},
handleAccountChange (account) {
this.selectedAccount = account
if (!this.isObjectEmpty(account)) {
this.fetchNetworkOfferingData()
}
},
fetchProjectData () {
this.networkOfferingWarning = false
this.projects = []
const params = {}
params.listall = true
params.showicon = true
params.details = 'min'
if (this.selectedDomain) {
params.domainid = this.selectedDomain.id
}
this.projectLoading = true
this.handleProjectChange(null)
api('listProjects', params).then(json => {
const listProjects = json.listprojectsresponse.project
this.projects = this.projects.concat(listProjects)
this.projects = json.listprojectsresponse.project || []
}).finally(() => {
this.projectLoading = false
if (this.arrayHasItems(this.projects)) {
if (this.arrayHasItems(this.projects) && this.scopeType === 'project') {
this.form.projectid = 0
this.handleProjectChange(this.projects[0])
} else {
this.form.projectid = null
}
})
},
handleProjectChange (project) {
this.selectedProject = project
if (!this.isObjectEmpty(project)) {
this.fetchNetworkOfferingData()
}
},
handleSubmit (e) {
if (this.actionLoading) return
@ -714,18 +898,26 @@ export default {
params.isolatedpvlan = values.isolatedpvlan
}
}
if (this.selectedNetwork) {
params.associatednetworkid = this.selectedNetwork.id
}
if (this.scopeType !== 'all') {
params.domainid = this.selectedDomain.id
params.acltype = this.scopeType
if (this.scopeType === 'account') { // account-specific
params.account = values.account
params.domainid = this.selectedAccount.domainid
params.account = this.selectedAccount.name
} else if (this.scopeType === 'project') { // project-specific
params.acltype = 'account'
params.domainid = this.selectedProject.domainid
params.projectid = this.selectedProject.id
} else { // domain-specific
params.subdomainaccess = this.parseBooleanValueForKey(values, 'subdomainaccess')
}
} else { // zone-wide
} else if (isAdminOrDomainAdmin()) { // zone-wide
params.acltype = 'domain' // server-side will make it Root domain (i.e. domainid=1)
} else {
params.acltype = 'account' // acl type is "account" for regular users
}
// IPv4 (begin)
if (this.isValidTextValueForKey(values, 'ip4gateway')) {

View File

@ -0,0 +1,135 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
<template>
<a-table
size="small"
style="overflow-y: auto"
:columns="columns"
:dataSource="networks"
:rowKey="item => item.id"
:pagination="false"
:loading="fetchLoading"
>
<template #name="{ text, record }">
<router-link v-if="record.issystem === false && !record.projectid" :to="{ path: '/guestnetwork/' + record.id }" >{{ text }}</router-link>
<router-link v-else-if="record.issystem === false && record.projectid" :to="{ path: '/guestnetwork/' + record.id, query: { projectid: record.projectid}}" >{{ text }}</router-link>
<span v-else>{{ text }}</span>
</template>
<template #state="{ record }">
<status :text="record.state" displayText></status>
</template>
</a-table>
</template>
<script>
import { api } from '@/api'
import Status from '@/components/widgets/Status'
export default {
name: 'GuestVlanNetworksTab',
components: {
Status
},
props: {
resource: {
type: Object,
required: true
},
loading: {
type: Boolean,
default: false
}
},
data () {
return {
fetchLoading: false,
networks: [],
columns: [
{
title: this.$t('label.name'),
dataIndex: 'name',
slots: { customRender: 'name' }
},
{
title: this.$t('label.type'),
dataIndex: 'type'
},
{
title: this.$t('label.state'),
slots: { customRender: 'state' }
},
{
title: this.$t('label.broadcasturi'),
dataIndex: 'broadcasturi'
},
{
title: this.$t('label.domain'),
dataIndex: 'domain'
},
{
title: this.$t('label.account'),
dataIndex: 'account'
},
{
title: this.$t('label.project'),
dataIndex: 'project'
},
{
title: this.$t('label.vpc'),
dataIndex: 'vpc'
}
]
}
},
created () {
this.fetchData()
},
watch: {
resource: function (newItem, oldItem) {
if (!newItem || !newItem.id) {
return
}
this.fetchData()
}
},
methods: {
fetchData () {
var params = {
id: this.resource.id
}
this.fetchLoading = true
api('listGuestVlans', params).then(json => {
this.networks = json.listguestvlansresponse.guestvlan[0].network || []
}).catch(error => {
this.$notifyError(error)
}).finally(() => {
this.fetchLoading = false
})
}
}
}
</script>
<style lang="scss" scoped>
.status {
margin-top: -5px;
&--end {
margin-left: 5px;
}
}
</style>

View File

@ -0,0 +1,207 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
<template>
<div>
<a-spin :spinning="fetchLoading">
<a-button
shape="round"
style="float: right;margin-bottom: 10px; z-index: 8"
@click="() => { showCreateForm = true }">
<template #icon><plus-outlined /></template>
{{ $t('label.add.network.permission') }}
</a-button>
<a-button
shape="round"
style="float: right;margin-bottom: 10px; z-index: 8"
@click="showResetPermissionModal = true"
:disabled="!('createNetworkPermissions' in $store.getters.apis)">
<template #icon><minus-outlined /></template>
{{ $t('label.action.reset.network.permissions') }}
</a-button>
<br />
<br />
<a-table
size="small"
style="overflow-y: auto; width: 100%;"
:columns="columns"
:dataSource="networkpermissions"
:rowKey="item => item.id"
:pagination="false" >
<template #action="{ record }">
<a-popconfirm
:title="$t('message.confirm.remove.network.permission')"
@confirm="removeNetworkPermission(record.accountid, record.projectid)"
:okText="$t('label.yes')"
:cancelText="$t('label.no')" >
<tooltip-button
tooltipPlacement="bottom"
:tooltip="$t('label.action.delete.network.permission')"
type="primary"
:danger="true"
icon="delete-outlined" />
</a-popconfirm>
</template>
</a-table>
<a-divider/>
</a-spin>
<a-modal
v-if="showCreateForm"
:visible="showCreateForm"
:title="$t('label.add.network.permission')"
:maskClosable="false"
:closable="true"
:footer="null"
@cancel="() => { showCreateForm = false }"
centered
width="auto">
<CreateNetworkPermission
:resource="resource"
@refresh-data="fetchData"
@close-action="showCreateForm = false" />
</a-modal>
<a-modal
:visible="showResetPermissionModal"
:title="$t('label.action.reset.network.permissions')"
:maskClosable="false"
:closable="true"
:footer="null"
@cancel="showResetPermissionModal = false"
centered
width="auto"
v-ctrl-enter="resetNetworkPermission">
{{ $t('message.confirm.reset.network.permissions') }}
<a-form @submit="resetNetworkPermission">
<div :span="24" class="action-button">
<a-button @click="showResetPermissionModal = false">{{ $t('label.cancel') }}</a-button>
<a-button type="primary" ref="submit" @click="resetNetworkPermission">{{ $t('label.ok') }}</a-button>
</div>
</a-form>
</a-modal>
</div>
</template>
<script>
import { api } from '@/api'
import CreateNetworkPermission from '@/views/network/CreateNetworkPermission'
import TooltipButton from '@/components/widgets/TooltipButton'
export default {
name: 'NetworkPermissions',
components: {
CreateNetworkPermission,
TooltipButton
},
props: {
resource: {
type: Object,
required: true
},
loading: {
type: Boolean,
default: false
}
},
data () {
return {
showResetPermissionModal: false,
fetchLoading: false,
showCreateForm: false,
total: 0,
networkpermissions: [],
page: 1,
pageSize: 10,
columns: [
{
title: this.$t('label.domain'),
dataIndex: 'domain'
},
{
title: this.$t('label.account'),
dataIndex: 'account'
},
{
title: this.$t('label.project'),
dataIndex: 'project'
},
{
title: '',
slots: { customRender: 'action' }
}
]
}
},
created () {
this.fetchData()
},
watch: {
resource: {
deep: true,
handler (newItem) {
if (!newItem || !newItem.id) {
return
}
this.fetchData()
}
}
},
methods: {
fetchData () {
const params = {
networkid: this.resource.id
}
this.fetchLoading = true
api('listNetworkPermissions', params).then(json => {
this.total = json.listnetworkpermissionsresponse.count || 0
this.networkpermissions = json.listnetworkpermissionsresponse.networkpermission || []
}).finally(() => {
this.fetchLoading = false
})
},
removeNetworkPermission (accountId, projectId) {
const params = {
networkid: this.resource.id
}
if (projectId) {
params.projectids = projectId
} else {
params.accountids = accountId
}
api('removeNetworkPermissions', params).then(json => {
this.$notification.success({
message: this.$t('message.success.remove.network.permissions')
})
}).finally(() => {
this.fetchData()
})
},
resetNetworkPermission () {
api('resetNetworkPermissions', {
networkid: this.resource.id
}).then(json => {
this.$notification.success({
message: this.$t('message.success.reset.network.permissions')
})
}).finally(() => {
this.fetchData()
this.showResetPermissionModal = false
})
}
}
}
</script>

View File

@ -170,7 +170,7 @@
</a-select-option>
</a-select>
</a-form-item>
<a-form-item :label="$t('label.vlan')" :required="true" ref="vlan" name="vlan">
<a-form-item :label="$t('label.vlan')" ref="vlan" name="vlan" v-if="this.isAdmin()">
<a-input
:placeholder="placeholders.vlan"
v-model:value="form.vlan"
@ -180,24 +180,41 @@
ref="bypassvlanoverlapcheck"
name="bypassvlanoverlapcheck"
:label="$t('label.bypassvlanoverlapcheck')"
v-if="$store.getters.apis.createPrivateGateway && $store.getters.apis.createPrivateGateway.params.filter(x => x.name === 'bypassvlanoverlapcheck').length > 0" >
v-if="this.isAdmin()">
<a-checkbox
v-model:checked="form.bypassvlanoverlapcheck"
></a-checkbox>
</a-form-item>
<a-form-item :label="$t('label.publicip')" :required="true" ref="ipaddress" name="ipaddress">
<a-form-item :label="$t('label.associatednetwork')" ref="associatednetworkid" name="associatednetworkid">
<a-select
v-model:value="form.associatednetwork"
showSearch
optionFilterProp="label"
:filterOption="(input, option) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
}" >
<a-select-option v-for="(opt, optIndex) in this.associatedNetworks" :key="optIndex" :label="opt.name || opt.description" :value="opt.id">
<span>
<resource-icon v-if="opt && opt.icon" :image="opt.icon.base64image" size="1x" style="margin-right: 5px"/>
<user-outlined style="margin-right: 5px" />
{{ opt.name || opt.description }}
</span>
</a-select-option>
</a-select>
</a-form-item>
<a-form-item :label="$t('label.publicip')" ref="ipaddress" name="ipaddress">
<a-input
:placeholder="placeholders.ipaddress"
v-model:value="form.ipaddress"
></a-input>
</a-form-item>
<a-form-item :label="$t('label.gateway')" :required="true" ref="gateway" name="gateway">
<a-form-item :label="$t('label.gateway')" ref="gateway" name="gateway">
<a-input
:placeholder="placeholders.gateway"
v-model:value="form.gateway"
></a-input>
</a-form-item>
<a-form-item :label="$t('label.netmask')" :required="true" ref="netmask" name="netmask">
<a-form-item :label="$t('label.netmask')" ref="netmask" name="netmask">
<a-input
:placeholder="placeholders.netmask"
v-model:value="form.netmask"
@ -383,6 +400,7 @@ export default {
return {
fetchLoading: false,
privateGateways: [],
associatedNetworks: [],
vpnGateways: [],
vpnConnections: [],
networkAcls: [],
@ -492,6 +510,9 @@ export default {
this.form = reactive({})
this.rules = reactive({})
},
isAdmin () {
return ['Admin'].includes(this.$store.getters.userInfo.roletype)
},
setCurrentTab () {
this.currentTab = this.$route?.query?.tab || 'details'
},
@ -558,6 +579,22 @@ export default {
}).finally(() => {
this.fetchLoading = false
})
this.associatedNetworks = []
api('listNetworks', {
domainid: this.resource.domainid,
account: this.resource.account,
listAll: true,
networkfilter: 'Account'
}).then(json => {
var networks = json.listnetworksresponse.network || []
for (const network of networks) {
if (network.type === 'Isolated' || network.type === 'L2') {
this.associatedNetworks.push(network)
}
}
}).catch(error => {
this.$notifyError(error)
})
},
fetchVpnGateways () {
this.fetchLoading = true
@ -609,6 +646,10 @@ export default {
},
fetchPhysicalNetworks () {
this.modals.gatewayLoading = true
if (!this.isAdmin()) {
this.modals.gatewayLoading = false
return
}
api('listPhysicalNetworks', { zoneid: this.resource.zoneid }).then(json => {
this.physicalnetworks = json.listphysicalnetworksresponse.physicalnetwork
if (this.modals.gateway === true) {
@ -639,7 +680,6 @@ export default {
switch (e) {
case 'privateGateways':
this.rules = {
vlan: [{ required: true, message: this.$t('label.required') }],
ipaddress: [{ required: true, message: this.$t('label.required') }],
gateway: [{ required: true, message: this.$t('label.required') }],
netmask: [{ required: true, message: this.$t('label.required') }]
@ -676,12 +716,17 @@ export default {
ipaddress: data.ipaddress,
gateway: data.gateway,
netmask: data.netmask,
vlan: data.vlan,
aclid: data.acl
}
if (data.bypassvlanoverlapcheck) {
params.bypassvlanoverlapcheck = data.bypassvlanoverlapcheck
}
if (data.vlan && String(data.vlan).length > 0) {
params.vlan = data.vlan
}
if (data.associatednetwork) {
params.associatednetworkid = data.associatednetwork
}
api('createPrivateGateway', params).then(response => {
this.$pollJob({

View File

@ -68,15 +68,7 @@
</a-radio-button>
</a-radio-group>
</a-form-item>
<a-row :gutter="12" v-if="guestType !== 'shared'">
<a-col :md="12" :lg="12">
<a-form-item name="ispersistent" ref="ispersistent">
<template #label>
<tooltip-label :title="$t('label.ispersistent')" :tooltip="apiParams.ispersistent.description"/>
</template>
<a-switch v-model:checked="form.ispersistent" />
</a-form-item>
</a-col>
<a-row :gutter="12">
<a-col :md="12" :lg="12">
<a-form-item name="specifyvlan" ref="specifyvlan">
<template #label>
@ -85,6 +77,14 @@
<a-switch v-model:checked="form.specifyvlan" />
</a-form-item>
</a-col>
<a-col :md="12" :lg="12">
<a-form-item name="ispersistent" ref="ispersistent" v-if="guestType !== 'shared'">
<template #label>
<tooltip-label :title="$t('label.ispersistent')" :tooltip="apiParams.ispersistent.description"/>
</template>
<a-switch v-model:checked="form.ispersistent" />
</a-form-item>
</a-col>
</a-row>
<a-form-item name="forvpc" ref="forvpc" v-if="guestType === 'isolated'">
<template #label>
@ -818,7 +818,9 @@ export default {
})
if (values.guestiptype === 'shared') { // specifyVlan checkbox is disabled, so inputData won't include specifyVlan
params.specifyvlan = true
if (values.specifyvlan === true) {
params.specifyvlan = true
}
params.specifyipranges = true
delete params.ispersistent
} else if (values.guestiptype === 'isolated') { // specifyVlan checkbox is shown