mirror of https://github.com/apache/cloudstack.git
track ip to vm mapping
This commit is contained in:
parent
f27116c50e
commit
b829cde18f
|
|
@ -81,6 +81,7 @@ import com.cloud.network.dao.NetworkDomainDaoImpl;
|
|||
import com.cloud.network.dao.NetworkRuleConfigDaoImpl;
|
||||
import com.cloud.network.lb.ElasticLoadBalancerManagerImpl;
|
||||
import com.cloud.network.lb.LoadBalancingRulesManagerImpl;
|
||||
import com.cloud.network.lb.dao.ElasticLbVmMapDaoImpl;
|
||||
import com.cloud.network.ovs.OvsNetworkManagerImpl;
|
||||
import com.cloud.network.ovs.OvsTunnelManagerImpl;
|
||||
import com.cloud.network.ovs.dao.GreTunnelDaoImpl;
|
||||
|
|
@ -270,6 +271,8 @@ public class DefaultComponentLibrary extends ComponentLibraryBase implements Com
|
|||
addDao("DcDetailsDao", DcDetailsDaoImpl.class);
|
||||
addDao("SwiftDao", SwiftDaoImpl.class);
|
||||
addDao("AgentTransferMapDao", HostTransferMapDaoImpl.class);
|
||||
addDao("ElasticLbVmMap", ElasticLbVmMapDaoImpl.class);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,102 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Citrix Systems, Inc. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the GNU General Public License v3 or later.
|
||||
*
|
||||
* It is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.cloud.network;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.PrimaryKeyJoinColumn;
|
||||
import javax.persistence.SecondaryTable;
|
||||
import javax.persistence.SecondaryTables;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import com.cloud.utils.net.Ip;
|
||||
|
||||
@Entity
|
||||
@Table(name = ("elastic_lb_vm_map"))
|
||||
@SecondaryTables({
|
||||
@SecondaryTable(name = "user_ip_address", pkJoinColumns = { @PrimaryKeyJoinColumn(name = "ip_addr_id", referencedColumnName = "id") })
|
||||
})
|
||||
public class ElasticLbVmMapVO {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private Long id;
|
||||
|
||||
@Column(name = "lb_id")
|
||||
private Long lbId;
|
||||
|
||||
@Column(name = "ip_addr_id")
|
||||
private long ipAddressId;
|
||||
|
||||
@Column(name = "elb_vm_id")
|
||||
private long elbVmId;
|
||||
|
||||
/*@Column(name = "name", table = "load_balancing_rules", insertable = false, updatable = false)
|
||||
private String lbName;*/
|
||||
|
||||
@Column(name = "public_ip_address", table = "user_ip_address", insertable = false, updatable = false)
|
||||
@Enumerated(value=EnumType.STRING)
|
||||
private Ip address = null;
|
||||
|
||||
public ElasticLbVmMapVO() {
|
||||
}
|
||||
|
||||
public ElasticLbVmMapVO(long ipId, long elbVmId) {
|
||||
this.ipAddressId = ipId;
|
||||
this.elbVmId = elbVmId;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public long getLbId() {
|
||||
return lbId;
|
||||
}
|
||||
|
||||
|
||||
public long getElbVmId() {
|
||||
return elbVmId;
|
||||
}
|
||||
|
||||
|
||||
// public String getLbName() {
|
||||
// return lbName;
|
||||
// }
|
||||
|
||||
|
||||
public long getIpAddressId() {
|
||||
return ipAddressId;
|
||||
}
|
||||
|
||||
public void setLbId(Long lbId) {
|
||||
this.lbId = lbId;
|
||||
}
|
||||
|
||||
public Ip getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -30,8 +30,8 @@ import com.cloud.network.rules.LoadBalancer;
|
|||
import com.cloud.user.Account;
|
||||
|
||||
public interface ElasticLoadBalancerManager {
|
||||
public static final int DEFAULT_ELB_VM_RAMSIZE = 512; // 512 MB
|
||||
public static final int DEFAULT_ELB_VM_CPU_MHZ = 500; // 500 MHz
|
||||
public static final int DEFAULT_ELB_VM_RAMSIZE = 128; // 512 MB
|
||||
public static final int DEFAULT_ELB_VM_CPU_MHZ = 256; // 500 MHz
|
||||
|
||||
public boolean applyLoadBalancerRules(Network network,
|
||||
List<? extends FirewallRule> rules)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
|
||||
* Copyright (C) 2011 Citrix Systems, Inc. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the GNU General Public License v3 or later.
|
||||
*
|
||||
|
|
@ -18,8 +18,6 @@
|
|||
package com.cloud.network.lb;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -42,10 +40,8 @@ import com.cloud.configuration.Config;
|
|||
import com.cloud.configuration.dao.ConfigurationDao;
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
import com.cloud.dc.HostPodVO;
|
||||
import com.cloud.dc.Pod;
|
||||
import com.cloud.dc.PodVlanMapVO;
|
||||
import com.cloud.dc.VlanVO;
|
||||
import com.cloud.dc.dao.ClusterDao;
|
||||
import com.cloud.dc.dao.DataCenterDao;
|
||||
import com.cloud.dc.dao.HostPodDao;
|
||||
|
|
@ -60,20 +56,19 @@ import com.cloud.exception.InvalidParameterValueException;
|
|||
import com.cloud.exception.OperationTimedoutException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.exception.StorageUnavailableException;
|
||||
import com.cloud.network.ElasticLbVmMapVO;
|
||||
import com.cloud.network.IPAddressVO;
|
||||
import com.cloud.network.IpAddress;
|
||||
import com.cloud.network.LoadBalancerVO;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.network.Network.GuestIpType;
|
||||
import com.cloud.network.NetworkManager;
|
||||
import com.cloud.network.NetworkVO;
|
||||
import com.cloud.network.PublicIpAddress;
|
||||
import com.cloud.network.Network.GuestIpType;
|
||||
import com.cloud.network.Networks.BroadcastDomainType;
|
||||
import com.cloud.network.addr.PublicIp;
|
||||
import com.cloud.network.dao.IPAddressDao;
|
||||
import com.cloud.network.dao.LoadBalancerDao;
|
||||
import com.cloud.network.dao.NetworkDao;
|
||||
import com.cloud.network.lb.LoadBalancingRule.LbDestination;
|
||||
import com.cloud.network.lb.dao.ElasticLbVmMapDao;
|
||||
import com.cloud.network.router.VirtualNetworkApplianceManager;
|
||||
import com.cloud.network.router.VirtualRouter;
|
||||
import com.cloud.network.router.VirtualRouter.Role;
|
||||
|
|
@ -83,7 +78,6 @@ import com.cloud.network.rules.LoadBalancer;
|
|||
import com.cloud.offering.NetworkOffering;
|
||||
import com.cloud.offerings.NetworkOfferingVO;
|
||||
import com.cloud.offerings.dao.NetworkOfferingDao;
|
||||
import com.cloud.org.Cluster;
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
import com.cloud.service.dao.ServiceOfferingDao;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
|
|
@ -96,7 +90,7 @@ import com.cloud.utils.Pair;
|
|||
import com.cloud.utils.component.Inject;
|
||||
import com.cloud.utils.component.Manager;
|
||||
import com.cloud.utils.db.DB;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.vm.DomainRouterVO;
|
||||
import com.cloud.vm.NicProfile;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
|
|
@ -153,6 +147,8 @@ public class ElasticLoadBalancerManagerImpl implements
|
|||
VlanDao _vlanDao;
|
||||
@Inject
|
||||
PodVlanMapDao _podVlanMapDao;
|
||||
@Inject
|
||||
ElasticLbVmMapDao _elbVmMapDao;
|
||||
|
||||
|
||||
String _name;
|
||||
|
|
@ -271,11 +267,12 @@ public class ElasticLoadBalancerManagerImpl implements
|
|||
}
|
||||
|
||||
protected DomainRouterVO findElbVmForLb(FirewallRule lb) {//TODO: use a table to lookup
|
||||
List<DomainRouterVO> elbVms = _routerDao.listByNetworkAndRole(lb.getNetworkId(), Role.LB);
|
||||
if (elbVms != null && elbVms.size() > 0)
|
||||
return elbVms.get(0);
|
||||
|
||||
return null;
|
||||
ElasticLbVmMapVO map = _elbVmMapDao.findOneByIp(lb.getSourceIpAddressId());
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
DomainRouterVO elbVm = _routerDao.findById(map.getElbVmId());
|
||||
return elbVm;
|
||||
}
|
||||
|
||||
public boolean applyLoadBalancerRules(Network network,
|
||||
|
|
@ -366,7 +363,6 @@ public class ElasticLoadBalancerManagerImpl implements
|
|||
return null;
|
||||
}
|
||||
|
||||
@DB
|
||||
public DomainRouterVO deployELBVm(Network guestNetwork, DeployDestination dest, Account owner, Map<Param, Object> params) throws
|
||||
ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
|
||||
long dcId = dest.getDataCenter().getId();
|
||||
|
|
@ -397,13 +393,7 @@ public class ElasticLoadBalancerManagerImpl implements
|
|||
DataCenterDeployment plan = null;
|
||||
DomainRouterVO elbVm = null;
|
||||
|
||||
//router = _routerDao.findByNetworkAndPodAndRole(guestNetwork.getId(), podId, Role.LB);
|
||||
plan = new DataCenterDeployment(dcId, null, null, null, null);
|
||||
|
||||
// } else {
|
||||
// s_logger.debug("Not deploying elastic ip vm");
|
||||
// return null;
|
||||
// }
|
||||
plan = new DataCenterDeployment(dcId, dest.getPod().getId(), null, null, null);
|
||||
|
||||
if (elbVm == null) {
|
||||
long id = _routerDao.getNextInSequence(Long.class, "id");
|
||||
|
|
@ -452,27 +442,50 @@ public class ElasticLoadBalancerManagerImpl implements
|
|||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public void handleCreateLoadBalancerRule( LoadBalancer lb, Account account) {
|
||||
|
||||
long ipId = lb.getSourceIpAddressId();
|
||||
IPAddressVO ipAddr = _ipAddressDao.findById(ipId);
|
||||
Long networkId= ipAddr.getSourceNetworkId();
|
||||
NetworkVO network=_networkDao.findById(networkId);
|
||||
DomainRouterVO elbVm = null;
|
||||
if (network.getGuestType() == GuestIpType.Direct) {
|
||||
LoadBalancerVO lbvo;
|
||||
lbvo = _lbDao.findByAccountAndName(account.getId(), lb.getName());
|
||||
if (lbvo == null) {
|
||||
elbVm = findELBVmWithCapacity(network, ipAddr);
|
||||
if (elbVm == null) {
|
||||
elbVm = deployLoadBalancerVM(networkId, ipAddr, account.getId());
|
||||
}
|
||||
IPAddressVO ipvo = _ipAddressDao.findById(ipId);
|
||||
ipvo.setAssociatedWithNetworkId(networkId);
|
||||
_ipAddressDao.update(ipvo.getId(), ipvo);
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (network.getGuestType() != GuestIpType.Direct) {
|
||||
s_logger.info("Elastic LB Manager: not handling guest traffic of type " + network.getGuestType());
|
||||
return;
|
||||
}
|
||||
DomainRouterVO elbVm = null;
|
||||
|
||||
LoadBalancerVO lbvo;
|
||||
lbvo = _lbDao.findByAccountAndName(account.getId(), lb.getName());
|
||||
if (lbvo == null) {
|
||||
elbVm = findELBVmWithCapacity(network, ipAddr);
|
||||
if (elbVm == null) {
|
||||
elbVm = deployLoadBalancerVM(networkId, ipAddr, account.getId());
|
||||
if (elbVm == null) {
|
||||
s_logger.warn("Failed to deploy a new ELB vm for ip " + ipAddr + " in network " + network + "lb name=" + lb.getName());
|
||||
return; //TODO: throw exception
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
ElasticLbVmMapVO elbVmMap = _elbVmMapDao.findOneByIp(lb.getSourceIpAddressId());
|
||||
if (elbVmMap != null) {
|
||||
elbVm = _routerDao.findById(elbVmMap.getElbVmId());
|
||||
}
|
||||
}
|
||||
if (elbVm == null) {
|
||||
s_logger.warn("No ELB VM can be found or deployed");
|
||||
return;
|
||||
}
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
txn.start();
|
||||
IPAddressVO ipvo = _ipAddressDao.findById(ipId);
|
||||
ipvo.setAssociatedWithNetworkId(networkId);
|
||||
_ipAddressDao.update(ipvo.getId(), ipvo);
|
||||
ElasticLbVmMapVO mapping = new ElasticLbVmMapVO(ipId, elbVm.getId());
|
||||
_elbVmMapDao.persist(mapping);
|
||||
txn.commit();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Citrix Systems, Inc. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the GNU General Public License v3 or later.
|
||||
*
|
||||
* It is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.cloud.network.lb.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.network.ElasticLbVmMapVO;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
public interface ElasticLbVmMapDao extends GenericDao<ElasticLbVmMapVO, Long> {
|
||||
ElasticLbVmMapVO findOneByLbIdAndElbVmId(long lbId, long elbVmId);
|
||||
ElasticLbVmMapVO findOneByIpIdAndElbVmId(long ipId, long elbVmId);
|
||||
ElasticLbVmMapVO findOneByIp(long ipId);
|
||||
|
||||
List<ElasticLbVmMapVO> listByElbVmId(long elbVmId);
|
||||
List<ElasticLbVmMapVO> listByLbId(long lbId);
|
||||
int deleteLB(long lbId);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/**
|
||||
* Copyright (C) 2011 Citrix Systems, Inc. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the GNU General Public License v3 or later.
|
||||
*
|
||||
* It is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.cloud.network.lb.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.ejb.Local;
|
||||
|
||||
import com.cloud.network.ElasticLbVmMapVO;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
|
||||
@Local(value={ElasticLbVmMapDao.class})
|
||||
public class ElasticLbVmMapDaoImpl extends GenericDaoBase<ElasticLbVmMapVO, Long> implements ElasticLbVmMapDao {
|
||||
private SearchBuilder<ElasticLbVmMapVO> AllFieldsSearch;
|
||||
|
||||
protected ElasticLbVmMapDaoImpl() {
|
||||
AllFieldsSearch = createSearchBuilder();
|
||||
AllFieldsSearch.and("ipId", AllFieldsSearch.entity().getIpAddressId(), SearchCriteria.Op.EQ);
|
||||
AllFieldsSearch.and("lbId", AllFieldsSearch.entity().getLbId(), SearchCriteria.Op.EQ);
|
||||
AllFieldsSearch.and("elbVmId", AllFieldsSearch.entity().getElbVmId(), SearchCriteria.Op.EQ);
|
||||
AllFieldsSearch.done();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElasticLbVmMapVO findOneByLbIdAndElbVmId(long lbId, long elbVmId) {
|
||||
SearchCriteria<ElasticLbVmMapVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("lbId", lbId);
|
||||
sc.setParameters("elbVmId", elbVmId);
|
||||
return findOneBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ElasticLbVmMapVO> listByLbId(long lbId) {
|
||||
SearchCriteria<ElasticLbVmMapVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("lbId", lbId);
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ElasticLbVmMapVO> listByElbVmId(long elbVmId) {
|
||||
SearchCriteria<ElasticLbVmMapVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("elbVmId", elbVmId);
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteLB(long lbId) {
|
||||
SearchCriteria<ElasticLbVmMapVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("lbId", lbId);
|
||||
return super.expunge(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElasticLbVmMapVO findOneByIpIdAndElbVmId(long ipId, long elbVmId) {
|
||||
SearchCriteria<ElasticLbVmMapVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("ipId", ipId);
|
||||
sc.setParameters("elbVmId", elbVmId);
|
||||
return findOneBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElasticLbVmMapVO findOneByIp(long ipId) {
|
||||
SearchCriteria<ElasticLbVmMapVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("ipId", ipId);
|
||||
return findOneBy(sc);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.cloud.network.dao;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import com.cloud.network.ElasticLbVmMapVO;
|
||||
import com.cloud.network.lb.dao.ElasticLbVmMapDaoImpl;
|
||||
import com.cloud.utils.component.ComponentLocator;
|
||||
|
||||
public class ElbVmMapDaoTest extends TestCase {
|
||||
public void testTags() {
|
||||
ElasticLbVmMapDaoImpl dao = ComponentLocator.inject(ElasticLbVmMapDaoImpl.class);
|
||||
|
||||
ElasticLbVmMapVO map = dao.findOneByIp(3);
|
||||
if (map == null) {
|
||||
System.out.println("Not Found");
|
||||
} else {
|
||||
System.out.println("Found");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1542,4 +1542,15 @@ CREATE TABLE `cloud`.`op_host_transfer` (
|
|||
CONSTRAINT `fk_op_host_transfer__future_mgmt_server_id` FOREIGN KEY `fk_op_host_transfer__future_mgmt_server_id`(`future_mgmt_server_id`) REFERENCES `mshost`(`msid`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `cloud`.`elastic_lb_vm_map` (
|
||||
`id` bigint unsigned NOT NULL auto_increment,
|
||||
`ip_addr_id` bigint unsigned NOT NULL,
|
||||
`elb_vm_id` bigint unsigned NOT NULL,
|
||||
`lb_id` bigint unsigned,
|
||||
PRIMARY KEY (`id`),
|
||||
CONSTRAINT `fk_elastic_lb_vm_map__ip_id` FOREIGN KEY `fk_elastic_lb_vm_map__ip_id` (`ip_addr_id`) REFERENCES `user_ip_address` (`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_elastic_lb_vm_map__elb_vm_id` FOREIGN KEY `fk_elastic_lb_vm_map__elb_vm_id` (`elb_vm_id`) REFERENCES `domain_router` (`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_elastic_lb_vm_map__lb_id` FOREIGN KEY `fk_elastic_lb_vm_map__lb_id` (`lb_id`) REFERENCES `load_balancing_rules` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
SET foreign_key_checks = 1;
|
||||
|
|
|
|||
Loading…
Reference in New Issue