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 ...
随机推荐
- 特别翔实的adaboost分类算法讲解 转的
转https://www.cnblogs.com/litthorse/p/9332370.html 作为(曾)被认为两大最好的监督分类算法之一的adaboost元算法(另一个为前几节介绍过的SVM算法 ...
- mysql concat_ws 与 concat 多字段模糊匹配应用
有时我们希望在表中多个字段检索是否有我们给出的关键字,我们可以使用 concat_ws 和 concat 连接需要检索的字段,如: select * from userInfo where conca ...
- Mask RCNN 原理
转自:https://blog.csdn.net/ghw15221836342/article/details/80084861 https://blog.csdn.net/ghw1522183634 ...
- Hadoop生态圈-Kafka的旧API实现生产者-消费者
Hadoop生态圈-Kafka的旧API实现生产者-消费者 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.旧API实现生产者-消费者 1>.开启kafka集群 [yinz ...
- Python远程连接模块-Telnet
Python远程连接模块-Telnet 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 虽然现在主流的python版本还是2.7,相信2020年python程序员都会偏向Python ...
- np.random.rand均匀分布随机数和np.random.randn正态分布随机数函数使用方法
np.random.rand用法 觉得有用的话,欢迎一起讨论相互学习~Follow Me 生成特定形状下[0,1)下的均匀分布随机数 np.random.rand(a1,a2,a3...)生成形状为( ...
- angularJs实现级联操作
angular实现级联非常的方便比起传统的jq和js来说,一般我们肯定是从后台获取一个list,然后生成一个下拉框,然后选中一个下拉框,得到id,再得到下一个list. 这些angular都给我做好了 ...
- python学习笔记6--操作Mysql
一.mysql操作 import pymysql #连上mysql ip 端口号 密码 账号 数据库 #建立游标 #执行sql #获取结果 #关闭连接.关闭游标 conn=pymysql.connec ...
- 正则tips
在啃Sizzle源码,被几个正则表达式给难住了,写了一下正则demo,记录一下 1,按照定义[]和(?:)里的内容不计入捕获组的数目 2,捕获组的计数顺序是,从大到小,同级从左到右 例如 var re ...
- [原]Android开发优化-Adapter优化
ListView作为Android开发中使用频率最高的一个控件,保证ListView的流畅运行,对用户体验的提高至关重要.Adapter是ListView和数据源之间的中间人,当每条数据进入可见区时, ...