Merge pull request #1689 from wanyaoqi/feature/wyq/auto-create-subnet

feature: auto create subnet on host register
This commit is contained in:
yunion-ci-robot
2019-07-20 13:32:04 +08:00
committed by GitHub
3 changed files with 187 additions and 8 deletions
+111
View File
@@ -1834,6 +1834,117 @@ func (self *SNetwork) PerformSplit(ctx context.Context, userCred mcclient.TokenC
return nil, nil
}
func (manager *SNetworkManager) AllowPerformTryCreateNetwork(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return db.IsAdminAllowClassPerform(userCred, manager, "try-create-network")
}
func (manager *SNetworkManager) PerformTryCreateNetwork(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
ip, err := data.GetString("ip")
if err != nil {
return nil, httperrors.NewMissingParameterError("ip")
}
ipV4, err := netutils.NewIPV4Addr(ip)
if err != nil {
return nil, httperrors.NewInputParameterError("ip")
}
mask, err := data.Int("mask")
if err != nil {
return nil, httperrors.NewMissingParameterError("mask")
}
serverType, err := data.GetString("server_type")
if err != nil {
return nil, httperrors.NewMissingParameterError("server_type")
}
if serverType != api.NETWORK_TYPE_BAREMETAL {
return nil, httperrors.NewBadRequestError("Only support server type %s", api.NETWORK_TYPE_BAREMETAL)
}
if !jsonutils.QueryBoolean(data, "is_on_premise", false) {
return nil, httperrors.NewBadRequestError("Only support on premise network")
}
var (
ipV4NetAddr = ipV4.NetAddr(int8(mask))
nm *SNetwork
matched bool
)
q := NetworkManager.Query().Equals("server_type", serverType).Equals("guest_ip_mask", mask)
q = managedResourceFilterByCloudType(q, query, "wire_id", func() *sqlchemy.SQuery {
wires := WireManager.Query().SubQuery()
vpcs := VpcManager.Query().SubQuery()
subq := wires.Query(wires.Field("id"))
subq = subq.Join(vpcs, sqlchemy.Equals(vpcs.Field("id"), wires.Field("vpc_id")))
return subq
})
rows, err := q.Rows()
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
item, err := db.NewModelObject(NetworkManager)
if err != nil {
return nil, err
}
err = q.Row2Struct(rows, item)
if err != nil {
return nil, err
}
n := item.(*SNetwork)
if n.GetIPRange().Contains(ipV4) {
nm = n
matched = true
break
} else if nIpV4, _ := netutils.NewIPV4Addr(n.GuestIpStart); nIpV4.NetAddr(n.GuestIpMask) == ipV4NetAddr {
nm = n
matched = false
break
}
}
ret := jsonutils.NewDict()
if nm == nil {
ret.Set("find_matched", jsonutils.JSONFalse)
return ret, nil
} else {
ret.Set("find_matched", jsonutils.JSONTrue)
ret.Set("wire_id", jsonutils.NewString(nm.WireId))
}
if !matched {
log.Infof("Find same subnet network %s %s/%d", nm.Name, nm.GuestGateway, nm.GuestIpMask)
newNetwork := new(SNetwork)
newNetwork.SetModelManager(NetworkManager, newNetwork)
newNetwork.GuestIpStart = ip
newNetwork.GuestIpEnd = ip
newNetwork.GuestGateway = nm.GuestGateway
newNetwork.GuestIpMask = int8(mask)
newNetwork.GuestDns = nm.GuestDns
newNetwork.GuestDhcp = nm.GuestDhcp
newNetwork.WireId = nm.WireId
newNetwork.ServerType = serverType
newNetwork.IsPublic = nm.IsPublic
newNetwork.ProjectId = userCred.GetProjectId()
newNetwork.DomainId = userCred.GetProjectDomainId()
newName, err := db.GenerateName(NetworkManager, userCred, fmt.Sprintf("%s#", nm.Name))
if err != nil {
return nil, httperrors.NewInternalServerError("GenerateName fail %s", err)
}
newNetwork.Name = newName
err = NetworkManager.TableSpec().Insert(newNetwork)
if err != nil {
return nil, err
}
err = newNetwork.CustomizeCreate(ctx, userCred, userCred, query, data)
if err != nil {
return nil, err
}
newNetwork.PostCreate(ctx, userCred, userCred, query, data)
}
return ret, nil
}
func (network *SNetwork) getAllocTimoutDuration() time.Duration {
tos := network.AllocTimoutSeconds
if tos < options.Options.MinimalIpAddrReusedIntervalSeconds {
+71 -8
View File
@@ -499,6 +499,19 @@ func (h *SHostInfo) detectiveOvsVersion() {
}
}
func (h *SHostInfo) GetMasterNicIpAndMask() (string, int) {
if h.MasterNic != nil {
mask, _ := h.MasterNic.Mask.Size()
return h.MasterNic.Addr, mask
}
for _, n := range h.Nics {
if len(n.Ip) > 0 {
return n.Ip, n.Mask
}
}
return "", 0
}
func (h *SHostInfo) GetMasterIp() string {
if h.MasterNic != nil {
return h.MasterNic.Addr
@@ -562,27 +575,76 @@ func (h *SHostInfo) onFail() {
panic("register failed, try 30 seconds later...")
}
// try to create network on region.
func (h *SHostInfo) tryCreateNetworkOnWire() {
masterIp, mask := h.GetMasterNicIpAndMask()
log.Debugf("Get master ip %s and mask %d", masterIp, mask)
if len(masterIp) == 0 || mask == 0 {
return
}
params := jsonutils.NewDict()
params.Set("ip", jsonutils.NewString(masterIp))
params.Set("mask", jsonutils.NewInt(int64(mask)))
params.Set("is_on_premise", jsonutils.JSONTrue)
params.Set("server_type", jsonutils.NewString(api.NETWORK_TYPE_BAREMETAL))
ret, err := modules.Networks.PerformClassAction(
hostutils.GetComputeSession(context.Background()),
"try-create-network", params)
if err != nil {
log.Errorf("try create network get error %s", err)
h.onFail()
}
if !jsonutils.QueryBoolean(ret, "find_matched", false) {
log.Errorf("Fail to get network info: no networks")
h.onFail()
}
wireId, err := ret.GetString("wire_id")
if err != nil {
log.Errorf("Fail to get network info: no wire id")
h.onFail()
}
h.onGetWireId(wireId)
}
func (h *SHostInfo) fetchAccessNetworkInfo() {
masterIp := h.GetMasterIp()
if len(masterIp) == 0 {
panic("master ip not found")
}
log.Debugf("Master ip %s to fetch wire", masterIp)
params := jsonutils.NewDict()
params.Set("ip", jsonutils.NewString(masterIp))
params.Set("is_on_premise", jsonutils.JSONTrue)
params.Set("limit", jsonutils.NewInt(0))
wire, err := hostutils.GetWireOfIp(context.Background(), params)
res, err := modules.Networks.List(h.GetSession(), params)
if err != nil {
log.Errorln(err)
h.onFail()
}
if len(res.Data) == 0 {
h.tryCreateNetworkOnWire()
} else if len(res.Data) == 1 {
wireId, _ := res.Data[0].GetString("wire_id")
h.onGetWireId(wireId)
} else {
log.Errorf("Fail to get network info: no networks")
h.onFail()
}
}
func (h *SHostInfo) onGetWireId(wireId string) {
wire, err := hostutils.GetWireInfo(context.Background(), wireId)
if err != nil {
log.Errorln(err)
h.onFail()
}
h.ZoneId, err = wire.GetString("zone_id")
if err != nil {
log.Errorln(err)
h.onFail()
} else {
h.ZoneId, err = wire.GetString("zone_id")
if err != nil {
log.Errorln(err)
h.onFail()
} else {
h.getZoneInfo(h.ZoneId, false)
}
h.getZoneInfo(h.ZoneId, false)
}
}
@@ -591,6 +653,7 @@ func (h *SHostInfo) GetSession() *mcclient.ClientSession {
}
func (h *SHostInfo) getZoneInfo(zoneId string, standalone bool) {
log.Debugf("Start GetZoneInfo %s %v", zoneId, standalone)
var params = jsonutils.NewDict()
params.Set("standalone", jsonutils.NewBool(standalone))
res, err := modules.Zones.Get(h.GetSession(),
+5
View File
@@ -188,6 +188,7 @@ type SNIC struct {
Ip string
Network string
WireId string
Mask int
Bandwidth int
BridgeDev hostbridge.IBridgeDriver
@@ -250,6 +251,10 @@ func NewNIC(desc string) (*SNIC, error) {
for wait < max {
inf := netutils2.NewNetInterface(nic.Inter)
if inf.Addr == nic.Ip {
mask, _ := inf.Mask.Size()
if mask > 0 {
nic.Mask = mask
}
break
}
br := netutils2.NewNetInterface(nic.Bridge)