Skip to content
48 changes: 31 additions & 17 deletions scripts/kvm/async_job/apply_second_ips.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,61 @@
cd `dirname $0`
source ../../cloudrc

[ $# -lt 4 ] && echo "$0 <vm_ID> <mac> <os_code> <update_meta>" && exit -1
[ $# -lt 4 ] && echo "$0 <vm_ID> <mac> <os_code> <update_meta> [primary_ip] [gateway]" && exit -1

ID=$1
vm_ID=inst-$ID
mac=$2
os_code=$3
update_meta=$4
primary_ip=$5
gateway=${6%/*}
more_addresses=$(cat)
naddrs=$(jq length <<< $more_addresses)
naddrs=$(jq length <<< "$more_addresses")

i=0
while [ $i -lt $naddrs ]; do
read -d'\n' -r address < <(jq -r ".[$i]" <<<$more_addresses)
read -d'\n' -r ip netmask < <(ipcalc -nb $address | awk '/Address/ {print $2} /Netmask/ {print $2}')
second_addrs_json="$second_addrs_json,{
\"type\": \"ipv4\",
\"ip_address\": \"$ip\",
\"netmask\": \"$netmask\",
\"link\": \"eth0\",
\"id\": \"network0\"
}"
let i=$i+1
done
if [ "$update_meta" != true ]; then
log_debug "no need to update any ip addresses"
exit 0
fi

if [ "$os_code" = "windows" ]; then
wait_qemu_ping $ID 10
if [ -n "$primary_ip" ]; then
read -d'\n' -r ip netmask < <(ipcalc -nb $primary_ip | awk '/Address/ {print $2} /Netmask/ {print $2}')
virsh qemu-agent-command "$vm_ID" '{"execute":"guest-exec","arguments":{"path":"C:\\Windows\\System32\\netsh.exe","arg":["interface","ipv4","set","address","name=eth0","addr='"$ip"'","mask='"$netmask"'"],"capture-output":true}}'
fi
i=0
while [ $i -lt $naddrs ]; do
read -d'\n' -r address < <(jq -r ".[$i]" <<<$more_addresses)
read -d'\n' -r address < <(jq -r ".[$i]" <<< "$more_addresses")
read -d'\n' -r ip netmask < <(ipcalc -nb $address | awk '/Address/ {print $2} /Netmask/ {print $2}')
virsh qemu-agent-command "$vm_ID" '{"execute":"guest-exec","arguments":{"path":"C:\\Windows\\System32\\netsh.exe","arg":["interface","ipv4","add","address","name=eth0","addr='"$ip"'","mask='"$netmask"'"],"capture-output":true}}'
let i=$i+1
done
elif [ "$os_code" = "linux" -a "$update_meta" = "true" ]; then
elif [ "$os_code" = "linux" ]; then
i=0
while [ $i -lt $naddrs ]; do
read -d'\n' -r address < <(jq -r ".[$i]" <<< "$more_addresses")
read -d'\n' -r ip netmask < <(ipcalc -nb $address | awk '/Address/ {print $2} /Netmask/ {print $2}')
second_addrs_json="$second_addrs_json,{
\"type\": \"ipv4\",
\"ip_address\": \"$ip\",
\"netmask\": \"$netmask\",
\"link\": \"eth0\",
\"id\": \"network0\"
}"
let i=$i+1
done
tmp_mnt=/tmp/mnt-$vm_ID
working_dir=/tmp/$vm_ID
latest_dir=$working_dir/openstack/latest
mkdir -p $tmp_mnt $working_dir
mount ${cache_dir}/meta/${vm_ID}.iso $tmp_mnt
cp -r $tmp_mnt/* $working_dir
net_json=$(cat $latest_dir/network_data.json)
if [ -n "$primary_ip" ]; then
read -d'\n' -r ip netmask < <(ipcalc -nb $primary_ip | awk '/Address/ {print $2} /Netmask/ {print $2}')
net_json=$(jq --arg ip "$ip" --arg netmask "$netmask" --arg gateway "$gateway" '.networks[] |= (select(.id == "network0" and .routes[0].network == "0.0.0.0") | .ip_address = $ip | .netmask = $netmask | .routes[0].gateway = $gateway)' <<< "$net_json")
fi
networks="[$(jq -r '.networks[] | select(.id == "network0" and .routes[0].network == "0.0.0.0")' <<<$net_json)$second_addrs_json]"
echo "$net_json" | jq --argjson new_networks "$networks" '.networks |= (map(select(.id != "network0")) + $new_networks)' >$latest_dir/network_data.json
umount $tmp_mnt
Expand Down
4 changes: 2 additions & 2 deletions scripts/kvm/attach_vm_nic.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ async_exec ./send_spoof_arp.py "$vm_br" "${ip%/*}" "$mac"
./set_subnet_gw.sh "$router" "$vlan" "$gateway" "$ext_vlan"
./set_host.sh "$router" "$vlan" "$mac" "$vm_name" "$ip"
more_addresses=$(jq -r .more_addresses <<< $vlan_info)
if [ -n "$more_addresses" ]; then
./apply_second_ips.sh "$ID" "$mac" "$os_code" "$update_meta" <<<$more_addresses
if [ -n "$more_addresses" -o "$update_meta" = true ]; then
./apply_second_ips.sh "$ID" "$mac" "$os_code" "$update_meta" "$ip" "$gateway" <<<$more_addresses
fi
echo "|:-COMMAND-:| $(basename $0) '$ID' '$mac' '$SCI_CLIENT_ID'"
2 changes: 1 addition & 1 deletion scripts/kvm/sync_nic_info.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
cd `dirname $0`
source ../cloudrc

[ $# -lt 3 ] && echo "$0 <vm_ID> <hostname> <os_code> <update_meta>" && exit -1
[ $# -lt 3 ] && echo "$0 <vm_ID> <hostname> <os_code> [update_meta]" && exit -1

ID=$1
vm_name=$2
Expand Down
12 changes: 12 additions & 0 deletions web/docs/alarm_rules_manager/alarm_v1_docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -6032,11 +6032,14 @@ const docTemplatealarm_v1 = `{
"minimum": 1
},
"disk_bps_limit": {
"description": "in MB/s",
"type": "integer",
"maximum": 102400,
"minimum": 0
},
"disk_iops_limit": {
"type": "integer",
"maximum": 10000000,
"minimum": 0
},
"flavor": {
Expand Down Expand Up @@ -6283,6 +6286,9 @@ const docTemplatealarm_v1 = `{
"maximum": 20000,
"minimum": 0
},
"primary_address": {
"$ref": "#/definitions/common.BaseReference"
},
"public_addresses": {
"type": "array",
"items": {
Expand Down Expand Up @@ -7789,7 +7795,9 @@ const docTemplatealarm_v1 = `{
"minimum": 0
},
"bps_limit": {
"description": "in MB/s",
"type": "integer",
"maximum": 102400,
"minimum": 0
},
"count": {
Expand All @@ -7803,6 +7811,7 @@ const docTemplatealarm_v1 = `{
},
"iops_limit": {
"type": "integer",
"maximum": 10000000,
"minimum": 0
},
"name": {
Expand All @@ -7820,11 +7829,14 @@ const docTemplatealarm_v1 = `{
"type": "object",
"properties": {
"bps_limit": {
"description": "in MB/s",
"type": "integer",
"maximum": 102400,
"minimum": 0
},
"iops_limit": {
"type": "integer",
"maximum": 10000000,
"minimum": 0
}
}
Expand Down
12 changes: 12 additions & 0 deletions web/docs/alarm_rules_manager/alarm_v1_swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -6026,11 +6026,14 @@
"minimum": 1
},
"disk_bps_limit": {
"description": "in MB/s",
"type": "integer",
"maximum": 102400,
"minimum": 0
},
"disk_iops_limit": {
"type": "integer",
"maximum": 10000000,
"minimum": 0
},
"flavor": {
Expand Down Expand Up @@ -6277,6 +6280,9 @@
"maximum": 20000,
"minimum": 0
},
"primary_address": {
"$ref": "#/definitions/common.BaseReference"
},
"public_addresses": {
"type": "array",
"items": {
Expand Down Expand Up @@ -7783,7 +7789,9 @@
"minimum": 0
},
"bps_limit": {
"description": "in MB/s",
"type": "integer",
"maximum": 102400,
"minimum": 0
},
"count": {
Expand All @@ -7797,6 +7805,7 @@
},
"iops_limit": {
"type": "integer",
"maximum": 10000000,
"minimum": 0
},
"name": {
Expand All @@ -7814,11 +7823,14 @@
"type": "object",
"properties": {
"bps_limit": {
"description": "in MB/s",
"type": "integer",
"maximum": 102400,
"minimum": 0
},
"iops_limit": {
"type": "integer",
"maximum": 10000000,
"minimum": 0
}
}
Expand Down
11 changes: 11 additions & 0 deletions web/docs/alarm_rules_manager/alarm_v1_swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -718,9 +718,12 @@ definitions:
minimum: 1
type: integer
disk_bps_limit:
description: in MB/s
maximum: 102400
minimum: 0
type: integer
disk_iops_limit:
maximum: 10000000
minimum: 0
type: integer
flavor:
Expand Down Expand Up @@ -900,6 +903,8 @@ definitions:
maximum: 20000
minimum: 0
type: integer
primary_address:
$ref: '#/definitions/common.BaseReference'
public_addresses:
items:
$ref: '#/definitions/common.BaseReference'
Expand Down Expand Up @@ -1912,6 +1917,8 @@ definitions:
minimum: 0
type: integer
bps_limit:
description: in MB/s
maximum: 102400
minimum: 0
type: integer
count:
Expand All @@ -1922,6 +1929,7 @@ definitions:
minimum: 0
type: integer
iops_limit:
maximum: 10000000
minimum: 0
type: integer
name:
Expand All @@ -1937,9 +1945,12 @@ definitions:
apis.VolumeQosPayload:
properties:
bps_limit:
description: in MB/s
maximum: 102400
minimum: 0
type: integer
iops_limit:
maximum: 10000000
minimum: 0
type: integer
type: object
Expand Down
3 changes: 3 additions & 0 deletions web/docs/routes/v1_docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -6225,6 +6225,9 @@ const docTemplatev1 = `{
"maximum": 20000,
"minimum": 0
},
"primary_address": {
"$ref": "#/definitions/common.BaseReference"
},
"public_addresses": {
"type": "array",
"items": {
Expand Down
3 changes: 3 additions & 0 deletions web/docs/routes/v1_swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -6218,6 +6218,9 @@
"maximum": 20000,
"minimum": 0
},
"primary_address": {
"$ref": "#/definitions/common.BaseReference"
},
"public_addresses": {
"type": "array",
"items": {
Expand Down
2 changes: 2 additions & 0 deletions web/docs/routes/v1_swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,8 @@ definitions:
maximum: 20000
minimum: 0
type: integer
primary_address:
$ref: '#/definitions/common.BaseReference'
public_addresses:
items:
$ref: '#/definitions/common.BaseReference'
Expand Down
26 changes: 26 additions & 0 deletions web/src/apis/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ type InterfacePatchPayload struct {
Name string `json:"name" binding:"omitempty,min=2,max=32"`
Inbound *int32 `json:"inbound" binding:"omitempty,min=0,max=20000"`
Outbound *int32 `json:"outbound" binding:"omitempty,min=0,max=20000"`
PrimaryAddress *BaseReference `json:"primary_address,omitempty"`
PublicAddresses []*BaseReference `json:"public_addresses,omitempty"`
Subnets []*BaseReference `json:"subnets" binding:"omitempty,gte=1,lte=32"`
Count *int `json:"count" binding:"omitempty,gte=1,lte=512"`
Expand Down Expand Up @@ -309,6 +310,8 @@ func (v *InterfaceAPI) Patch(c *gin.Context) {
var floatingIp *model.FloatingIp
floatingIp, err = floatingIpAdmin.GetFloatingIpByUUID(ctx, pubAddr.ID)
if err != nil {
logger.Errorf("Failed to get public ip")
ErrorResponse(c, http.StatusBadRequest, "Failed to get public ip", err)
return
}
publicIps = append(publicIps, floatingIp)
Expand Down Expand Up @@ -346,6 +349,29 @@ func (v *InterfaceAPI) Patch(c *gin.Context) {
}
siteSubnets = append(siteSubnets, siteSubnet)
}
if payload.PrimaryAddress != nil {
if !iface.PrimaryIf {
logger.Errorf("It is not allowed to update ip of secondary interface")
ErrorResponse(c, http.StatusBadRequest, "It is not allowed to update ip of secondary interface", err)
return
}
var primaryFip *model.FloatingIp
primaryFip, err = floatingIpAdmin.GetFloatingIpByUUID(ctx, payload.PrimaryAddress.ID)
if err != nil {
logger.Errorf("Failed to get primary public ip")
ErrorResponse(c, http.StatusBadRequest, "Failed to get primary public ip", err)
return
}
if primaryFip.ID != iface.FloatingIp {
for i, pubAddr := range publicIps {
if primaryFip.ID == pubAddr.ID {
publicIps = append(publicIps[:i], publicIps[i+1:]...)
break
}
}
publicIps = append([]*model.FloatingIp{primaryFip}, publicIps...)
}
}
err = interfaceAdmin.Update(ctx, instance, iface, ifaceName, inbound, outbound, allowSpoofing, secgroups, ifaceSubnets, siteSubnets, count, publicIps)
if err != nil {
logger.Errorf("Patch instance failed, %+v", err)
Expand Down
13 changes: 9 additions & 4 deletions web/src/common/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ func DeallocateAddress(ctx context.Context, ifaces []*model.Interface) (err erro
return
}

func genMacaddr() (mac string, err error) {
func GenerateMacaddr() (mac string, err error) {
buf := make([]byte, 4)
_, err = rand.Read(buf)
if err != nil {
Expand All @@ -188,11 +188,13 @@ func genMacaddr() (mac string, err error) {
return mac, nil
}

func DerivePublicInterface(ctx context.Context, instance *model.Instance, iface *model.Interface, floatingIps []*model.FloatingIp) (primaryIface *model.Interface, primarySubnet *model.Subnet, err error) {
func DerivePublicInterface(ctx context.Context, instance *model.Instance, iface *model.Interface, floatingIps []*model.FloatingIp, primaryMac string) (primaryIface *model.Interface, primarySubnet *model.Subnet, err error) {
ctx, db := GetContextDB(ctx)
primaryIface = iface
updatePrimary := false
if primaryIface == nil {
primaryIface = floatingIps[0].Interface
updatePrimary = true
}
primarySubnet = primaryIface.Address.Subnet
for _, address := range primaryIface.SecondAddresses {
Expand Down Expand Up @@ -227,7 +229,7 @@ func DerivePublicInterface(ctx context.Context, instance *model.Instance, iface
}
primaryIface.SecondAddresses = nil
for i, fip := range floatingIps {
if fip.InstanceID > 0 {
if !updatePrimary && fip.InstanceID > 0 {
continue
}
fip.Instance = instance
Expand All @@ -236,6 +238,9 @@ func DerivePublicInterface(ctx context.Context, instance *model.Instance, iface
primaryIface.Instance = instance.ID
primaryIface.Name = "eth0"
primaryIface.PrimaryIf = true
if primaryMac != "" {
primaryIface.MacAddr = primaryMac
}
err = db.Model(primaryIface).Updates(primaryIface).Error
if err != nil {
logger.Errorf("Failed to update interface, %v", err)
Expand Down Expand Up @@ -288,7 +293,7 @@ func CreateInterface(ctx context.Context, subnet *model.Subnet, ID, owner int64,
primary = true
}
if mac == "" {
mac, err = genMacaddr()
mac, err = GenerateMacaddr()
if err != nil {
logger.Error("Failed to generate random Mac address, %v", err)
return
Expand Down
Loading