IP基础知识与分配实现
一、IP寻址
1.划分网络ID和主机ID的最初方案是使用地址分类。
2.A类:0.0.0.0-127.255.255.255
B类:128.0.0.0-191.255.255.255
C类:192.0.0.0-223.255.255.255
D类:224.0.0.0-239.255.255.255
E类:240.0.0.0-247.255.255.255
二、子网
1.子网划分可以利用IP地址系统把物理网络分解为更小的逻辑实体——子网。
2.子网的概念最早源自于地址分类系统,而且在ABC类地址中能够得到很好的展现。然而硬件厂商和internet社区建立了一种解析地址的新系统,名为无类别域间路由(CIDR),它不需要关心地址类别。
192.168.1.0/24,它指的是IP地址是192.168.1.0,子网掩码中1的个数是24个,即255.255.255.0,二进制显示为11111111 11111111 11111111 00000000,很容易看出这个就是一个C类的网络,最后的八个0可以随意组合,取值范围为0-255。
同理192.168.1.0/29,指的是IP地址是192.168.1.0,子网掩码中1的个数是24个,即255.255.255.248,二进制显示为11111111 11111111 11111111 11111000,可用IP地址个数有8个,
一般首尾IP地址为特殊地址,不在实际中使用。
三、代码实现
以下提供两个在/24子网池下划分更小的子网(24< x < 32)和在/16子网池下划分更小的子网(16< x < 24)的实现类。注意:其中去掉了主要的业务逻辑代码,仅提供了IP分配的算法实现。因为需要启用的IP地址比较多,使用了源生的JDBC事务来提高执行效率。备注:此处使用的springCloud框架,底层实现仅供参考。
3.1、基础PO
package com.ccb.cloud.nw.ip.data.entity;
// default package import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient; /**
* NwCclassPo entity. @author MyEclipse Persistence Tools
*/
@Entity
@Table(name="RM_NW_CCLASS") public class NwCclassPo implements java.io.Serializable { // Fields private Long cclassId;
private Long bclassId;
private String cclassTypeCode;
private String secureAreaCode;
private String cclassName;
private String subnetmask;
private String gateway;
private Long vlanId;
private String isActive;
private String secureTierCode;
private Integer aclassIp;
private Integer bclassIp;
private Integer cclassIp;
private Integer ipStart;
private Integer ipEnd; private Integer ipTotalCnt;
private Integer ipAvailCnt; private Long datacenterId;
private Long moduleId;
private Long vmManagerServerId;
private Long convergeId;
private String routersId; @Transient
private Integer useIpNum;
@Transient
private Integer unUseIpNum;
@Transient
private Long resPoolId;
@Transient
private String resPoolType;
@Transient
private String netArea;
// private RmNwSubnetmaskExtPo rmNwSubnetmaskExtPo; // Constructors /** default constructor */
public NwCclassPo() {
} /** minimal constructor */
public NwCclassPo(Long cclassId, Long bclassId) {
this.cclassId = cclassId;
this.bclassId = bclassId;
} /** full constructor */
public NwCclassPo(Long cclassId, Long bclassId, String cclassTypeCode, String secureAreaCode, String cclassName,
String subnetmask, String gateway, Long vlanId, String isActive, String secureTierCode, Integer aclassIp,
Integer bclassIp, Integer cclassIp, Integer ipStart, Integer ipEnd,Integer ipTotalCnt,Integer ipAvailCnt,Long datacenterId) {
this.cclassId = cclassId;
this.bclassId = bclassId;
this.cclassTypeCode = cclassTypeCode;
this.secureAreaCode = secureAreaCode;
this.cclassName = cclassName;
this.subnetmask = subnetmask;
this.gateway = gateway;
this.vlanId = vlanId;
this.isActive = isActive;
this.secureTierCode = secureTierCode;
this.aclassIp = aclassIp;
this.bclassIp = bclassIp;
this.cclassIp = cclassIp;
this.ipStart = ipStart;
this.ipEnd = ipEnd; this.ipTotalCnt=ipTotalCnt;
this.ipAvailCnt=ipAvailCnt;
this.datacenterId=datacenterId;
} // Property accessors
@Id @Column(name="CCLASS_ID", unique=true, nullable=false, precision=18, scale=0) public Long getCclassId() {
return this.cclassId;
} public void setCclassId(Long cclassId) {
this.cclassId = cclassId;
} @Column(name = "VCENTER_ID", nullable =true, precision = 18, scale = 0)
public Long getVmManagerServerId() {
return vmManagerServerId;
} public void setVmManagerServerId(Long vmManagerServerId) {
this.vmManagerServerId = vmManagerServerId;
} @Column(name = "MODULE_ID", nullable =true, precision = 18, scale = 0)
public Long getModuleId() {
return moduleId;
} public void setModuleId(Long moduleId) {
this.moduleId = moduleId;
} @Column(name="BCLASS_ID", nullable=false, precision=18, scale=0) public Long getBclassId() {
return this.bclassId;
} public void setBclassId(Long bclassId) {
this.bclassId = bclassId;
} @Column(name="CCLASS_TYPE_CODE", length=32) public String getCclassTypeCode() {
return this.cclassTypeCode;
} public void setCclassTypeCode(String cclassTypeCode) {
this.cclassTypeCode = cclassTypeCode;
} @Column(name="SECURE_AREA_CODE", length=32) public String getSecureAreaCode() {
return this.secureAreaCode;
} public void setSecureAreaCode(String secureAreaCode) {
this.secureAreaCode = secureAreaCode;
} @Column(name="CCLASS_NAME", length=100) public String getCclassName() {
return this.cclassName;
} public void setCclassName(String cclassName) {
this.cclassName = cclassName;
} @Column(name="SUBNETMASK", length=20) public String getSubnetmask() {
return this.subnetmask;
} public void setSubnetmask(String subnetmask) {
this.subnetmask = subnetmask;
} @Column(name="GATEWAY", length=20) public String getGateway() {
return this.gateway;
} public void setGateway(String gateway) {
this.gateway = gateway;
} @Column(name="VLAN_ID", precision=18, scale=0) public Long getVlanId() {
return this.vlanId;
} public void setVlanId(Long vlanId) {
this.vlanId = vlanId;
} @Column(name="IS_ACTIVE", length=1) public String getIsActive() {
return this.isActive;
} public void setIsActive(String isActive) {
this.isActive = isActive;
} @Column(name="SECURE_TIER_CODE", length=32) public String getSecureTierCode() {
return this.secureTierCode;
} public void setSecureTierCode(String secureTierCode) {
this.secureTierCode = secureTierCode;
} @Column(name="ACLASS_IP", precision=3, scale=0) public Integer getAclassIp() {
return this.aclassIp;
} public void setAclassIp(Integer aclassIp) {
this.aclassIp = aclassIp;
} @Column(name="BCLASS_IP", precision=3, scale=0) public Integer getBclassIp() {
return this.bclassIp;
} public void setBclassIp(Integer bclassIp) {
this.bclassIp = bclassIp;
} @Column(name="CCLASS_IP", precision=3, scale=0) public Integer getCclassIp() {
return this.cclassIp;
} public void setCclassIp(Integer cclassIp) {
this.cclassIp = cclassIp;
} @Column(name="IP_START", precision=3, scale=0) public Integer getIpStart() {
return this.ipStart;
} public void setIpStart(Integer ipStart) {
this.ipStart = ipStart;
} @Column(name="IP_END", precision=3, scale=0) public Integer getIpEnd() {
return this.ipEnd;
} public void setIpEnd(Integer ipEnd) {
this.ipEnd = ipEnd;
} //
@Column(name="IP_TOTAL_CNT", precision=3, scale=0) public Integer getIpTotalCnt() {
return this.ipTotalCnt;
} public void setIpTotalCnt(Integer ipTotalCnt) {
this.ipTotalCnt = ipTotalCnt;
} @Column(name="IP_AVAIL_CNT", precision=3, scale=0) public Integer getIpAvailCnt() {
return this.ipAvailCnt;
} public void setIpAvailCnt(Integer ipAvailCnt) {
this.ipAvailCnt = ipAvailCnt;
}
@Column(name = "DATACENTER_ID",length=18)
public Long getDatacenterId() {
return datacenterId;
} public void setDatacenterId(Long datacenterId) {
this.datacenterId = datacenterId;
}
@Column(name = "CONVERGE_ID", nullable =true, precision = 18, scale = 0)
public Long getConvergeId() {
return convergeId;
} public void setConvergeId(Long convergeId) {
this.convergeId = convergeId;
} @Column(name="ROUTERS_ID", length=36)
public String getRoutersId() {
return routersId;
} public void setRoutersId(String routersId) {
this.routersId = routersId;
} @Transient
public Integer getUseIpNum() {
return useIpNum;
} public void setUseIpNum(Integer useIpNum) {
this.useIpNum = useIpNum;
} @Transient
public Integer getUnUseIpNum() {
return unUseIpNum;
} public void setUnUseIpNum(Integer unUseIpNum) {
this.unUseIpNum = unUseIpNum;
} @Transient
public Long getResPoolId() {
return resPoolId;
} public void setResPoolId(Long resPoolId) {
this.resPoolId = resPoolId;
} @Transient
public String getResPoolType() {
return resPoolType;
} public void setResPoolType(String resPoolType) {
this.resPoolType = resPoolType;
} @Transient
public String getNetArea() {
return netArea;
} public void setNetArea(String netArea) {
this.netArea = netArea;
} }
NwCclassPo
package com.ccb.cloud.nw.ip.data.entity; import java.io.Serializable;
import javax.persistence.*;
import java.util.Date; /**
* The persistent class for the RM_CDP_IP_ADDRESS database table.
*
*/
@Entity
@Table(name="RM_CDP_IP_ADDRESS")
public class RmCdpIpAddressPo implements Serializable {
private static final long serialVersionUID = 1L; @Id
private String ip; @Column(name="ALLOCED_STATUS_CODE")
private String allocedStatusCode; @Temporal(TemporalType.DATE)
@Column(name="ALLOCED_TIME")
private Date allocedTime; @Column(name="APP_DU_ID")
private Long appDuId; @Column(name="CCLASS_ID")
private Long cclassId; @Column(name="DEVICE_ID")
private Long deviceId; @Column(name="IP_TYPE_ID")
private String ipTypeId; private String remark; @Column(name="RES_CDP_ID")
private Long resCdpId; @Column(name="RES_CLUSTER_ID")
private Long resClusterId; @Column(name="RES_POOL_ID")
private Long resPoolId; private Integer seq; public RmCdpIpAddressPo() {
} public String getIp() {
return ip;
} public void setIp(String ip) {
this.ip = ip;
} public String getAllocedStatusCode() {
return allocedStatusCode;
} public void setAllocedStatusCode(String allocedStatusCode) {
this.allocedStatusCode = allocedStatusCode;
} public Date getAllocedTime() {
return allocedTime;
} public void setAllocedTime(Date allocedTime) {
this.allocedTime = allocedTime;
} public Long getAppDuId() {
return appDuId;
} public void setAppDuId(Long appDuId) {
this.appDuId = appDuId;
} public Long getCclassId() {
return cclassId;
} public void setCclassId(Long cclassId) {
this.cclassId = cclassId;
} public Long getDeviceId() {
return deviceId;
} public void setDeviceId(Long deviceId) {
this.deviceId = deviceId;
} public String getIpTypeId() {
return ipTypeId;
} public void setIpTypeId(String ipTypeId) {
this.ipTypeId = ipTypeId;
} public String getRemark() {
return remark;
} public void setRemark(String remark) {
this.remark = remark;
} public Long getResCdpId() {
return resCdpId;
} public void setResCdpId(Long resCdpId) {
this.resCdpId = resCdpId;
} public Long getResClusterId() {
return resClusterId;
} public void setResClusterId(Long resClusterId) {
this.resClusterId = resClusterId;
} public Long getResPoolId() {
return resPoolId;
} public void setResPoolId(Long resPoolId) {
this.resPoolId = resPoolId;
} public Integer getSeq() {
return seq;
} public void setSeq(Integer seq) {
this.seq = seq;
} public RmCdpIpAddressPo(String ip, String allocedStatusCode, Date allocedTime, Long appDuId, Long cclassId,
Long deviceId, String ipTypeId, String remark, Long resCdpId, Long resClusterId, Long resPoolId,
Integer seq) {
super();
this.ip = ip;
this.allocedStatusCode = allocedStatusCode;
this.allocedTime = allocedTime;
this.appDuId = appDuId;
this.cclassId = cclassId;
this.deviceId = deviceId;
this.ipTypeId = ipTypeId;
this.remark = remark;
this.resCdpId = resCdpId;
this.resClusterId = resClusterId;
this.resPoolId = resPoolId;
this.seq = seq;
} }
RmCdpIpAddressPo
3.2 DAO仅提供SQL
//获取名称对应的子网信息
@Query(value="select * from rm_cdp_ip_address a where a.ip = :ip",nativeQuery=true)
RmCdpIpAddressPo getIpInfoByIp(@Param("ip") String ip); //获取名称对应的子网信息
@Query(value="SELECT t.cclass_id,t.bclass_id,t.cclass_type_code,t.secure_area_code,t.secure_tier_code,t.cclass_name,t.subnetmask,t.gateway,t.vlan_id," +
"t.ip_start,t.ip_end,t.aclass_ip,t.bclass_ip,t.cclass_ip,t.ip_total_cnt,t.ip_avail_cnt,t.is_active,t.datacenter_id,t.module_id,t.vcenter_id,t.converge_id,t.template_id,t.routers_id"
+ " FROM rm_nw_cclass t WHERE t.cclass_name=:cclassName ",nativeQuery=true)
List<NwCclassPo> getBclassByName(@Param("cclassName") String cclassName);
3.3 Service实现
package com.ccb.cloud.nw.ip.service; import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map; import javax.sql.DataSource; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.web.client.RestTemplate; import com.ccb.cloud.common.data.DBSeqUtils;
import com.ccb.cloud.common.exception.BizException;
import com.ccb.cloud.common.service.BaseService;
import com.ccb.cloud.common.util.ExDateUtils;
import com.ccb.cloud.nw.ip.constants.IpFwConstants;
import com.ccb.cloud.nw.ip.data.dao.RmCdpIpAddressDAO;
import com.ccb.cloud.nw.ip.data.dao.RmNwCclassDAO;
import com.ccb.cloud.nw.ip.data.entity.NwCclassPo;
import com.ccb.cloud.nw.ip.data.entity.RmCdpIpAddressPo;
import com.ccb.cloud.nw.ip.data.entity.RmNwCclassFreelistPo;
import com.ccb.cloud.nw.ip.data.entity.RmNwSubnetmaskExtPo;
/**
* @author liuqiang.zh
*@version
*/
@Service
@Transactional(readOnly = true)
public class Temp extends BaseService<NwCclassPo> {
private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired
JdbcTemplate jdbcTemplate; @Autowired
RestTemplate restTemplate; @Autowired
private RmNwCclassDAO rmNwCclassDAO; @Autowired
private RmCdpIpAddressDAO rmCdpIpAddressDAO; /**
* 在/24子网池下批量新增按子网掩码和个数分配的子网表
* 在子网表记录创建成功后批量新增ip地址表记录
* @author liuqiang.zh
* @param paramBody
*/
public String batchSaveSubCclassAndCclassField(Map<String, Object> paramBody) throws Exception{
String result = "";
long startTime = System.currentTimeMillis();
//调用通用方法获取C段列表,遍历
String cclassNameTemp = (String)paramBody.get("className");
String[] cclassNameTempList = cclassNameTemp.split("/");
String cclassName = cclassNameTempList[0];
//子网池掩码
String poolSubnetmaskStr = cclassNameTempList[1];
Integer poolSubnetmask = 0;
if(!"".equals(poolSubnetmaskStr)) {
poolSubnetmask = Integer.parseInt(poolSubnetmaskStr);
} if(poolSubnetmask < IpFwConstants.BMAXIPUNIT) {
//调用B段启用方法
return batchSaveSubCclassByBName(paramBody);
}
if("".equals(cclassName)) {
throw new BizException("001", "未获取到传入的C段Ip");
}
String[] CIpNumberList = cclassName.split("\\.");
Integer aclassIp = Integer.parseInt(CIpNumberList[0]);
Integer bclassIp = Integer.parseInt(CIpNumberList[1]);
Integer cclassIp = Integer.parseInt(CIpNumberList[2]);
//获取子网掩码格式,判断?是否小于/24子网(24-32)
Integer subNetMaskUnit = 0;
Object subnetmaskTempStr = paramBody.get("subnetmask");
if(subnetmaskTempStr !=null && !"".equals(subnetmaskTempStr)) {
subNetMaskUnit = Integer.parseInt(subnetmaskTempStr.toString());
}
if(subNetMaskUnit < IpFwConstants.BMAXIPUNIT || subNetMaskUnit >= IpFwConstants.MAXIPUNIT) {
throw new BizException("001", "输入的子网掩码超出范围");
}
//获取子网个数,判断?当前C段剩余的按子网格式分配的子网个数是否大于选择的子网个数
Integer subNumber = 0;
Object subNumberTempStr = paramBody.get("subNumber");
if(subNumberTempStr !=null && !"".equals(subNumberTempStr)) {
subNumber = Integer.parseInt(subNumberTempStr.toString());
} //获取最小单元的位数
int subUnit = IpFwConstants.MAXIPUNIT - subNetMaskUnit;
//最小单元存放的IP个数
int ipUnit = (int)Math.pow(IpFwConstants.BASICUNIT, subUnit);
//默认值
Long bclassId = 0L;
List<NwCclassPo> rmNwCclassList = new ArrayList<>();
//批量新增IP表记录
List<RmCdpIpAddressPo> ipsList =new ArrayList<>();
//若为0,重新开始生成子网,若不为0,取最后一条记录的网关,并将此IP +1作为起始的地址
Integer startIp = 0;
RmCdpIpAddressPo rmCdpIpAddressPoTemp = null;
for(int i=0;i < IpFwConstants.MAXIPNUMBER/ipUnit;i++) {
//当前的C段数字
int curCIp = i*ipUnit+1;
String subCclassName = aclassIp+"."+bclassIp+"."+cclassIp+"."+curCIp;
//此处去IP表中查找当前掩码格式下第一个IP,是否存在?若不存在,则取当前起始IP
rmCdpIpAddressPoTemp = rmCdpIpAddressDAO.getIpInfoByIp(subCclassName); if(rmCdpIpAddressPoTemp == null) {
startIp = i*ipUnit;
break;
}
if(i == IpFwConstants.MAXIPNUMBER/ipUnit-1) {
startIp = IpFwConstants.MAXIPNUMBER;
}
} //获取子网个数,判断?当前C段剩余的按子网格式分配的子网个数是否大于选择的子网个数
int availNum = (int)(IpFwConstants.MAXIPNUMBER - startIp)/ipUnit; Date date = ExDateUtils.getCurrentDateTime();
//判断已经生成的子网个数
int count = 0;
RmCdpIpAddressPo rmCdpIpAddressPoTest = null;
if(subNumber <= availNum) {
for(int i=0;i < availNum;i++) {
//首先需要判断IP是否超出256的最大范围
if((startIp+(i+1)*ipUnit) > IpFwConstants.MAXIPNUMBER) {
throw new BizException("001", "待启用的子网个数不满足选择需求");
}
if(subNumber == count) {
break;
}
//此处重新去IP表中查找第一个IP是否存在
String testCclassName = aclassIp+"."+bclassIp+"."+cclassIp+"."+(startIp+i*ipUnit+1);
rmCdpIpAddressPoTest = rmCdpIpAddressDAO.getIpInfoByIp(testCclassName);
if(rmCdpIpAddressPoTest == null) {
NwCclassPo cclassPo = new NwCclassPo();
Long cclassId = DBSeqUtils.getSeq("IOMP_SEQ");
String subCclassName = aclassIp+"."+bclassIp+"."+cclassIp+"."+(startIp+i*ipUnit);
String gateway = aclassIp+"."+bclassIp+"."+cclassIp+"."+(startIp+(i+1)*ipUnit-IpFwConstants.BASICUNIT);
Integer ipStart = startIp+i*ipUnit + 1;
Integer ipEnd = startIp+(i+1)*ipUnit - IpFwConstants.BASICUNIT;
Integer ipTotalCnt = ipUnit;
Integer ipAvailCnt = ipUnit -IpFwConstants.BASICUNIT;
cclassPo.setCclassId(cclassId);
cclassPo.setBclassId(bclassId);
cclassPo.setCclassName(subCclassName);
cclassPo.setSubnetmask(subNetMaskUnit.toString());
cclassPo.setGateway(gateway);
cclassPo.setIpStart(ipStart);
cclassPo.setIpEnd(ipEnd);
cclassPo.setAclassIp(aclassIp);
cclassPo.setBclassIp(bclassIp);
cclassPo.setCclassIp(cclassIp);
cclassPo.setIpTotalCnt(ipTotalCnt);
cclassPo.setIpAvailCnt(ipAvailCnt); rmNwCclassList.add(cclassPo); //生成对应的IP表数据
String[] topCclassNameList = subCclassName.split("\\.");
Integer aclassIpAddr = Integer.parseInt(topCclassNameList[0]);
Integer bclassIpAddr = Integer.parseInt(topCclassNameList[1]);
Integer cclassIpAddr = Integer.parseInt(topCclassNameList[2]);
Integer dclassIpAddr = Integer.parseInt(topCclassNameList[3]);
for(int j=0;j < ipUnit-IpFwConstants.BASICUNIT;j++) {
RmCdpIpAddressPo ipAddressPo = new RmCdpIpAddressPo();
String curIpAddress = aclassIpAddr+"."+bclassIpAddr+"."+cclassIpAddr+"."+(dclassIpAddr+j+1) ;
ipAddressPo.setIp(curIpAddress);
ipAddressPo.setCclassId(cclassId);
ipAddressPo.setSeq(dclassIpAddr+j+1);
//待定字段值ALLOCED_STATUS_CODE
ipAddressPo.setAllocedStatusCode(IpFwConstants.NOTALLOCATE);
ipAddressPo.setAllocedTime(date);
ipsList.add(ipAddressPo);
}
count++;
}
}
}else {
throw new BizException("001", "没有足够的子网可供分配");
} Connection connection = null;
DataSource dataSource = null;
try {
TransactionSynchronizationManager.clearSynchronization();
if (!TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.initSynchronization();
}
dataSource = jdbcTemplate.getDataSource();
connection = DataSourceUtils.getConnection(dataSource);
connection.setAutoCommit(false);
if(rmNwCclassList.size() > 0) {
saveNwCclassPoList(rmNwCclassList);
}
if(ipsList.size() > 0) {
saveIpAddressList(ipsList);
result += "OK";
connection.commit();
}
long endTime = System.currentTimeMillis();
logger.info("***************启用C段子网耗时:{}",endTime - startTime);
} catch(Exception e) {
try {
connection.rollback();
} catch (SQLException e1) {
logger.error("启用子网报错:", e1);
}
logger.error("启用子网报错:", e);
} finally {
try {
TransactionSynchronizationManager.clearSynchronization();
} catch (IllegalStateException e) {
logger.error("启用子网报错:", e);
connection.rollback();
}
TransactionSynchronizationManager.initSynchronization(); try {
connection.setAutoCommit(true);
} catch (SQLException e) {
logger.error("启用子网报错:", e);
connection.rollback();
} if (connection != null) {
DataSourceUtils.releaseConnection(connection, dataSource);
}
}
return result;
} /**
* 在/16子网池下批量新增按子网掩码和个数分配的子网表
* 在子网表记录创建成功后批量新增ip地址表记录
* @author liuqiang.zh
* @param paramBody
*/
// @Transactional(readOnly = false)
public String batchSaveSubCclassByBName(Map<String, Object> paramBody) throws Exception{
String result = "";
long startTime = System.currentTimeMillis();
//调用通用方法获取C段列表,遍历
String cclassNameTemp = (String)paramBody.get("className");
String[] cclassNameTempList = cclassNameTemp.split("/");
String bclassName = cclassNameTempList[0];
//启用支持半个B段
Integer bclassType = 0;
String bclassTypeStr = cclassNameTempList[1];
if(bclassTypeStr != null && !"".equals(bclassTypeStr)) {
bclassType = Integer.parseInt(bclassTypeStr);
}
if("".equals(bclassName)) {
throw new BizException("001", "未获取到B段ip");
}
String[] CIpNumberList = bclassName.split("\\.");
Integer aclassIp = Integer.parseInt(CIpNumberList[0]);
Integer bclassIp = Integer.parseInt(CIpNumberList[1]);
//半个B段的起始Ip
Integer beginIp = Integer.parseInt(CIpNumberList[2]);
//获取子网掩码格式,判断?是否小于/16子网(16-24)
Integer subNetMaskUnit = 0;
Object subnetmaskTempStr = paramBody.get("subnetmask");
if(subnetmaskTempStr !=null && !"".equals(subnetmaskTempStr)) {
subNetMaskUnit = Integer.parseInt(subnetmaskTempStr.toString());
}
if(subNetMaskUnit < IpFwConstants.BUNIT || subNetMaskUnit > IpFwConstants.BMAXIPUNIT) {
throw new BizException("001", "输入的子网掩码超出范围!");
}
Integer subNumber = 0;
Object subNumberTempStr = paramBody.get("subNumber");
if(subNumberTempStr !=null && !"".equals(subNumberTempStr)) {
subNumber = Integer.parseInt(subNumberTempStr.toString());
}
//机房模块,安全区域,安全分层,网络汇聚,VC服务器,数据中心
String cclassTypeCode = String.valueOf(paramBody.get("cclassTypeCode"));
//获取最小单元的位数selfDefIp
int subUnit = IpFwConstants.BMAXIPUNIT - subNetMaskUnit;
//最小单元存放的IP个数
int ipUnit = (int)Math.pow(IpFwConstants.BASICUNIT, subUnit);
//此处先查询B段表信息,更新资源池ID
Long bclassId = 0L;
//获取起始位子IP
Integer startIp = 0;
//判断是否启用的是一个完整B段
if(bclassType > IpFwConstants.BUNIT) {
startIp = beginIp;
}
//子网池结束ip
int scope = (int)Math.pow(IpFwConstants.BASICUNIT,(IpFwConstants.BMAXIPUNIT-bclassType));
int endIp = beginIp+scope;
List<NwCclassPo> nwCclassPoTemp = null;
for(int i=0;i < scope/ipUnit;i++) {
//当前的C段数字
int curCIp = startIp+i*ipUnit;
String subCclassName = aclassIp+"."+bclassIp+"."+curCIp+".0";
//此处去子网表中查找当前子网格式下第一个IP,是否存在?若不存在,则取当前起始IP
nwCclassPoTemp = rmNwCclassDAO.getBclassByName(subCclassName);
if(nwCclassPoTemp.size() == 0 || nwCclassPoTemp.isEmpty()) {
startIp += i*ipUnit;
break;
}
if(i == IpFwConstants.MAXIPNUMBER/ipUnit-1) {
startIp = endIp;
}
}
//批量子网
List<NwCclassPo> rmNwCclassList = new ArrayList<>();
List<RmNwCclassFreelistPo> RmNwCclassFreelist = new ArrayList<>();
List<RmNwSubnetmaskExtPo> rmNwSubnetmaskExtList = new ArrayList<>();
//批量新增IP表记录
List<RmCdpIpAddressPo> ipsList =new ArrayList<>();
//获取子网个数,判断,当前C段剩余的按子网格式分配的子网个数是否大于选择的子网个数
int availNum = (int)(endIp - startIp)/ipUnit;
Date date = ExDateUtils.getCurrentDateTime();
//统计可用个数
int count = 0;
if(subNumber <= availNum) {
for(int i=0;i<subNumber;i++) {
//当前的C段数字,允许192.168.0.0/24子网
int curCIp = 0;
curCIp = startIp+i*ipUnit;
if(curCIp > endIp-1) {
throw new BizException("001", "可用的子网个数不足");
}
String subCclassName = aclassIp+"."+bclassIp+"."+curCIp+".0";
//此处去子网表中查找当前子网格式下第一个IP,是否存在?若不存在,则按
nwCclassPoTemp = rmNwCclassDAO.getBclassByName(subCclassName);
if(count == subNumber) {
break;
}
if(nwCclassPoTemp.size() == 0 || nwCclassPoTemp.isEmpty()) {
//子网表记录,这里与C段表为一对一关系
NwCclassPo cclassPo = new NwCclassPo();
RmNwCclassFreelistPo cclassFreePo = new RmNwCclassFreelistPo();
Long cclassId = DBSeqUtils.getSeq("IOMP_SEQ");
String gateway = aclassIp+"."+bclassIp+"."+curCIp+".254";
Integer ipStart = 1;
Integer ipEnd = IpFwConstants.MAXIPNUMBER-IpFwConstants.BASICUNIT;
Integer ipTotalCnt = IpFwConstants.MAXIPNUMBER;
Integer ipAvailCnt = IpFwConstants.MAXIPNUMBER -IpFwConstants.BASICUNIT;
cclassPo.setCclassId(cclassId);
cclassPo.setBclassId(bclassId);
//待定?
cclassPo.setCclassTypeCode(cclassTypeCode);
cclassPo.setCclassName(subCclassName);
cclassPo.setSubnetmask(subNetMaskUnit.toString());
cclassPo.setGateway(gateway);
cclassPo.setIpStart(ipStart);
cclassPo.setIpEnd(ipEnd);
cclassPo.setAclassIp(aclassIp);
cclassPo.setBclassIp(bclassIp);
cclassPo.setCclassIp(curCIp);
cclassPo.setIpTotalCnt(ipTotalCnt);
cclassPo.setIpAvailCnt(ipAvailCnt);
rmNwCclassList.add(cclassPo);
//子网扩展表数据
RmNwSubnetmaskExtPo rmNwSubnetmaskExtPo = new RmNwSubnetmaskExtPo();
rmNwSubnetmaskExtPo.setSubnetmaskId(cclassId);
//新增GatewayIp
rmNwSubnetmaskExtPo.setGatewayIp(gateway);
rmNwSubnetmaskExtPo.setIpVersion(4L);
rmNwSubnetmaskExtList.add(rmNwSubnetmaskExtPo);
//子网空闲表数据
cclassFreePo.setCclassId(cclassId);
cclassFreePo.setSeqStart(ipStart);
cclassFreePo.setSeqEnd(ipEnd);
cclassFreePo.setAvailCnt(ipAvailCnt);
RmNwCclassFreelist.add(cclassFreePo); //生成对应的IP表数据
for(int m=0;m < ipUnit;m++) {
for(int j=1;j <IpFwConstants.MAXIPNUMBER-1;j++) {
RmCdpIpAddressPo ipAddressPo = new RmCdpIpAddressPo();
String curIpAddress = aclassIp+"."+bclassIp+"."+(curCIp+m)+"."+j ;
ipAddressPo.setIp(curIpAddress);
ipAddressPo.setCclassId(cclassId);
ipAddressPo.setSeq(j);
//待定字段值ALLOCED_STATUS_CODE
ipAddressPo.setAllocedStatusCode(IpFwConstants.NOTALLOCATE);
ipAddressPo.setAllocedTime(date);
ipsList.add(ipAddressPo);
}
}
count++;
}
}
}else {
throw new BizException("001", "没有足够的子网可供分配");
} Connection connection = null;
DataSource dataSource = null;
try {
TransactionSynchronizationManager.clearSynchronization();
if (!TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.initSynchronization();
}
dataSource = jdbcTemplate.getDataSource();
connection = DataSourceUtils.getConnection(dataSource);
connection.setAutoCommit(false);
if(rmNwCclassList.size() > 0) {
saveNwCclassPoList(rmNwCclassList);
}
if(ipsList.size() > 0) {
saveIpAddressList(ipsList);
result += "OK";
connection.commit();
}
long endTime = System.currentTimeMillis();
logger.info("***************启用B段子网耗时:{}",endTime - startTime);
} catch(Exception e) {
try {
connection.rollback();
} catch (SQLException e1) {
logger.error("启用子网报错:", e1);
}
logger.error("启用子网报错:", e);
} finally {
try {
TransactionSynchronizationManager.clearSynchronization();
} catch (IllegalStateException e) {
logger.error("启用子网报错:", e);
connection.rollback();
}
TransactionSynchronizationManager.initSynchronization(); try {
connection.setAutoCommit(true);
} catch (SQLException e) {
logger.error("启用子网报错:", e);
connection.rollback();
} if (connection != null) {
DataSourceUtils.releaseConnection(connection, dataSource);
}
}
return result;
}
/**
* jdbcTemplate批量新增NwCclassPo表
* @param list
* @author liuqiang
*/
private void saveNwCclassPoList(final List<NwCclassPo> list) throws Exception{
String sql = "insert into RM_NW_CCLASS (CCLASS_ID,BCLASS_ID,CCLASS_TYPE_CODE,CCLASS_NAME,SUBNETMASK,\n" +
"GATEWAY,VLAN_ID,IP_START,IP_END,ACLASS_IP,BCLASS_IP,CCLASS_IP,IP_TOTAL_CNT,IP_AVAIL_CNT,IS_ACTIVE,DATACENTER_ID,SECURE_AREA_CODE,MODULE_ID)"
+ "values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { @Override
public int getBatchSize() {
return list.size();
} @Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
ps.setLong(1, list.get(i).getCclassId());
ps.setLong(2, list.get(i).getBclassId());
ps.setString(3, list.get(i).getCclassTypeCode());
ps.setString(4, list.get(i).getCclassName());
ps.setString(5, list.get(i).getSubnetmask());
ps.setString(6, list.get(i).getGateway());
if (list.get(i).getVlanId() != null) {
ps.setLong(7, list.get(i).getVlanId());
} else {
ps.setLong(7, 0);
}
ps.setInt(8, list.get(i).getIpStart());
ps.setInt(9, list.get(i).getIpEnd());
ps.setInt(10, list.get(i).getAclassIp());
ps.setInt(11, list.get(i).getBclassIp());
ps.setInt(12, list.get(i).getCclassIp());
ps.setInt(13, list.get(i).getIpTotalCnt());
ps.setInt(14, list.get(i).getIpAvailCnt());
ps.setString(15, list.get(i).getIsActive());
Long datacenterId = list.get(i).getDatacenterId();
if(datacenterId != null) {
ps.setLong(16, list.get(i).getDatacenterId());
}else {
ps.setLong(16, 0L);
}
ps.setString(17, list.get(i).getSecureAreaCode());
Long moduleId = list.get(i).getModuleId();
if(moduleId != null) {
ps.setLong(18, list.get(i).getModuleId());
}else {
ps.setLong(18, 0L);
}
}
});
} /**
* jdbcTemplate批量新增RmCdpIpAddressPo表
* @param list
* @author zhangchaoyang
*/
private void saveIpAddressList(final List<RmCdpIpAddressPo> list) throws Exception{
String sql = "insert into RM_CDP_IP_ADDRESS (IP,CCLASS_ID,SEQ,IP_TYPE_ID,RES_POOL_ID,ALLOCED_STATUS_CODE,ALLOCED_TIME) "
+ "values(?,?,?,?,?,?,?)";
this.jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { @Override
public int getBatchSize() {
return list.size();
} @Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
ps.setString(1, list.get(i).getIp());
ps.setLong(2, list.get(i).getCclassId());
ps.setInt(3, list.get(i).getSeq());
ps.setString(4, list.get(i).getIpTypeId());
if (list.get(i).getResPoolId() != null) {
ps.setLong(5, list.get(i).getResPoolId());
} else {
ps.setLong(5, 0);
}
ps.setString(6, list.get(i).getAllocedStatusCode());
ps.setDate(7, new java.sql.Date(list.get(i).getAllocedTime().getTime()));
}
});
}
}
Temp
3.4、常量Util
package com.ccb.cloud.nw.ip.constants; public class IpFwConstants {
//最大可用地址个数
public static final int MAXIPNUMBER = 256; //Cip地址总位数
public static final int MAXIPUNIT = 32; //Bip地址总位数
public static final int BMAXIPUNIT = 24; //完整B段位数
public static final int BUNIT = 16; //首位地址个数
public static final int BASICUNIT = 2; //防火墙网络地址类型
public static final String FWCCLASSTYPECODE = "FWINT"; //没有激活
public static final String NOTAVAILABLE = "N"; //激活
public static final String AVAILABLE = "Y"; //激活
public static final String HOLDPOSITION = "H"; //激活
public static final String NOTALLOCATE = "NA"; //最大可用地址个数
public static final String BCLASSSUBNETMASK = "255.255.0.0";
}
IpFwConstants
/**
* Copyright (c) 2017, China Construction Bank Co., Ltd. All rights reserved.
* 中国建设银行版权所有.
*
* 审核人:
*/
package com.ccb.cloud.common.data; import java.sql.Connection;
import java.sql.SQLException; import javax.sql.DataSource; import org.apache.commons.lang3.StringUtils;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition; import com.ccb.cloud.common.spring.SpringContextHolder; /**
* 主键序列号生成器,统一数据库主键生成方式 每次获取一定长度的序列号缓存到内存中,提高应用程序获取序列号的效率
*
* Oracle数据库采用序列生成序列号,MySQL数据库使用数据库表生成序列号
* <p>
*
* @author
* @version 1.0 2017年8月31日
* @see
*/
public class DBSeqUtils { // 默认序列名称
private static final String DEFAULT_SEQ_KEY = "MAIN_SEQ"; // 内存中序列长度(在Oracle数据中建立序列是,需要将序列的步长设置为500)
private static final long SEQ_LEN = 100; // 序列获取控制参数
private static long BEGIN_SEQ = 0 ;// 开始的序列号
private static long CURRENT_SEQ = 0;// 当前序列号 /**
* 获取默认的最新序列值
* @throws InterruptedException
*
*/
public static synchronized long getDefaultSeq(){ long seq; if (BEGIN_SEQ == 0 || CURRENT_SEQ == SEQ_LEN) {
// 重新获取序列
BEGIN_SEQ = getCurrentSeq();
CURRENT_SEQ = 0;
} seq = BEGIN_SEQ + CURRENT_SEQ;
CURRENT_SEQ++; return seq; } /**
* 获取序列的最新序列值
*
* @return
*/
public static long getSeq(String seqKey) { DataSource dataSource = SpringContextHolder.getBean("dataSource"); NamedParameterJdbcTemplate jdbcTemplate = new NamedParameterJdbcTemplate(
dataSource); return jdbcTemplate.getJdbcOperations()
.queryForObject(
"SELECT " + seqKey + ".nextval FROM dual",
Long.class); } /**
* 获取数据库中最新的序列值
*
* @return
*/
private static long getCurrentSeq() { DataSource dataSource = SpringContextHolder.getBean("dataSource"); String jdbcUrl = getJdbcUrlFromDataSource(dataSource); NamedParameterJdbcTemplate jdbcTemplate = new NamedParameterJdbcTemplate(
dataSource); // 根据jdbc url判断数据库类型
if (StringUtils.contains(jdbcUrl, ":mysql:")) {
return getMySqlCurrentSeqVal(jdbcTemplate);
} else if (StringUtils.contains(jdbcUrl, ":oracle:")) {
return jdbcTemplate.getJdbcOperations().queryForObject(
"SELECT " + DEFAULT_SEQ_KEY + ".nextval FROM dual",
Long.class);
} else {
throw new IllegalArgumentException("数据库驱动配置错误,不支持的类型:" + jdbcUrl);
}
} /**
* 获取mySql的当前序列值
* @param jdbcTemplate
*/
private static long getMySqlCurrentSeqVal(
NamedParameterJdbcTemplate jdbcTemplate) { long currentSeq = 0; // 更新序列值的大小
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
PlatformTransactionManager txManager = SpringContextHolder
.getBean("transactionManager");
TransactionStatus status = txManager.getTransaction(def); try { // 获取当前序列值
currentSeq = jdbcTemplate.getJdbcOperations().queryForObject(
"SELECT cur_seq_val FROM admin_seq WHERE seq_name='"
+ DEFAULT_SEQ_KEY + "' FOR UPDATE", Long.class); jdbcTemplate.getJdbcOperations().execute(
"UPDATE admin_seq set cur_seq_val="
+ (currentSeq + SEQ_LEN) + " WHERE seq_name='"
+ DEFAULT_SEQ_KEY + "'");
txManager.commit(status); } catch (RuntimeException e) {
txManager.rollback(status);
throw new RuntimeException("无法生成序列号",e);
} return currentSeq;
} /**
* 通过数据源获取数据库连接URL
*
* @param dataSource
* @return
*/
private static String getJdbcUrlFromDataSource(DataSource dataSource) {
Connection connection = null;
try {
connection = dataSource.getConnection();
if (connection == null) {
throw new IllegalStateException("数据源无法返回的connection");
}
return connection.getMetaData().getURL();
} catch (SQLException e) {
throw new RuntimeException("无法获取数据库的URL", e);
} finally {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
}
}
}
} }
DBSeqUtils
水平有限,程序中的考虑不周或者精简代码时产生的BUG希望大家自己斧正。
IP基础知识与分配实现的更多相关文章
- TCP/IP基础知识
TCP/IP基础知识 网络 TCP/IP 引言 本篇属于TCP/IP协议的基础知识,重点介绍了TCP/IP协议簇的内容.作用以及TCP.UDP.IP三种常见网络协议相关的基础知识. 内容 TCP/IP ...
- IP 基础知识全家桶,45 张图一套带走
前言 前段时间,有读者希望我写一篇关于 IP 分类地址.子网划分等的文章,他反馈常常混淆,摸不着头脑. 那么,说来就来!而且要盘就盘全一点,顺便挑战下小林的图解功力,所以就来个 IP 基础知识全家桶. ...
- 第二章 TCP/IP 基础知识
第二章 TCP/IP 基础知识 TCP/IP transmission control protocol and ip internet protocol 是互联网众多通信协议中最为著名的. ...
- TCP/IP协议(二)tcp/ip基础知识
今天凌晨时候看书,突然想到一个问题:怎样做到持续学习?然后得出这样一个结论:放弃不必要的社交,控制欲望,克服懒惰... 然后又有了新的问题:学习效率时高时低,状态不好怎么解决?这也是我最近在思考的问题 ...
- 二、tcp/ip基础知识
一.TCP/IP的标准化 1.TCP/IP的含义 一般来说,TCP/IP是利用IP进行通信时所必须用到的协议群的统称. 具体点,IP或ICMP.TCP或UDP.TELENT或FTP.以及HTTP等都属 ...
- TCP/IP 基础知识
我把自己以往的文章汇总成为了 Github ,欢迎各位大佬 star https://github.com/crisxuan/bestJavaer 已提交此篇文章 要说我们接触计算机网络最多的协议,那 ...
- 图解 IP 基础知识!
我把自己以往的文章汇总成为了 Github ,欢迎各位大佬 star https://github.com/crisxuan/bestJavaer IP 协议 路由器对分组进行转发后,就会把数据包传到 ...
- HCIA SWITCHING&ROUTTING 笔记——第一章 TCP/IP基础知识(3)
4 ICMP协议 4.1 概念 ICMP即 Internet Contorl Message Protocol,即Internet控制消息协议,是网络层的一个重要协议.ICMP协议用来在网络设备间传递 ...
- HCIA SWITCHING&ROUTTING 笔记——第一章 TCP/IP基础知识(2)
视频地址:https://ilearningx.huawei.com/courses/course-v1:HuaweiX+EBGTC00000336+Self-paced/courseware/abb ...
随机推荐
- oracle之回滚数据表 笔记
alter table [tableName] enable row movement;flashback table [tableName] to timestamp to_timestamp('2 ...
- [整理]Win下好用的Markdown工具
用过haroopad,MarkPad,Sublime + markdown插件,前2款勉强能用,都处于继续开发中,haroopad支持的语法相对较少,提示也不明显,MarkPad还是有不少bug. 后 ...
- html之div始终停留在屏幕中间部分
需求: 使得某一个div始终停留在屏幕中间 实现: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ...
- rsync更改端口后的同步办法
rsync有两种常用的认证方式,一种为rsync-daemon方式,另外一种则是ssh. 在一些场合,使用rsync-daemon方式会比较缺乏灵活性,ssh方式则成为首选.但是今天实际操作的时候发现 ...
- Oracle 基本操作符
1.一般操作符 (1)!= 不等于 select empno,ename,job from scott.emp where job!='manager' (2)^= 不等于 select empno, ...
- GBDT理解
一.提升树 提升方法实际采用加法模型(即基函数的线性组合)与前向分布算法.以决策树为基函数的提升方法称为提升树,boosting tree.对分类问题的决策树是二叉分类树,对回归问题的决策树是二叉回归 ...
- mysql主键的缺少导致备库hang
最近线上频繁的出现slave延时的情况,经排查发现为用户在删除数据的时候,由于表主键的主键的缺少,同时删除条件没有索引,或或者删除的条件过滤性极差,导致slave出现hang住,严重的影响了生产环境的 ...
- USB-HID鼠标、键盘通讯格式【转】
转自:https://blog.csdn.net/techhome803/article/details/9928873 转自:http://www.amobbs.com/forum.php?mod= ...
- Linux磁盘分区UUID的获取及其UUID的作用
注:UUID-Universally Unique IDentifiers全局唯一标识符 一.Linux磁盘分区UUID的获取方法 1.[san@localhost ~]$ ls -l /dev/di ...
- mysql ON DUPLICATE KEY UPDATE重复插入时更新
mysql当插入重复时更新的方法: 第一种方法: 示例一:插入多条记录 假设有一个主键为 client_id 的 clients 表,可以使用下面的语句: INSERT INTO clients (c ...