Initial YakPanel commit
This commit is contained in:
384
class_v2/btdockerModelV2/networkModel.py
Normal file
384
class_v2/btdockerModelV2/networkModel.py
Normal file
@@ -0,0 +1,384 @@
|
||||
# coding: utf-8
|
||||
# -------------------------------------------------------------------
|
||||
# YakPanel
|
||||
# -------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2099 YakPanel(www.yakpanel.com) All rights reserved.
|
||||
# -------------------------------------------------------------------
|
||||
# Author: wzz <wzz@yakpanel.com>
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
import docker.errors
|
||||
|
||||
import gettext
|
||||
_ = gettext.gettext
|
||||
# ------------------------------
|
||||
# Docker模型
|
||||
# ------------------------------
|
||||
import public
|
||||
|
||||
from btdockerModelV2 import dk_public as dp
|
||||
from btdockerModelV2.dockerBase import dockerBase
|
||||
from public.validate import Param
|
||||
|
||||
class main(dockerBase):
|
||||
|
||||
def docker_client(self, url):
|
||||
return dp.docker_client(url)
|
||||
|
||||
def get_network_id(self, get):
|
||||
"""
|
||||
asdf
|
||||
@param get:
|
||||
@return:
|
||||
"""
|
||||
networks = self.docker_client(self._url).networks
|
||||
network = networks.get(get.id)
|
||||
return network.attrs
|
||||
|
||||
def get_host_network(self, get):
|
||||
"""
|
||||
获取服务器的docker网络
|
||||
:param get:
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
client = self.docker_client(self._url)
|
||||
if not client:
|
||||
return public.return_message(-1, 0, [])
|
||||
|
||||
networks = client.networks
|
||||
network_attr = self.get_network_attr(networks)
|
||||
|
||||
data = list()
|
||||
|
||||
for attr in network_attr:
|
||||
get.id = attr["Id"]
|
||||
c_result = self.get_network_id(get)
|
||||
subnet = ""
|
||||
gateway = ""
|
||||
subnetv6 = ""
|
||||
gatewayv6 = ""
|
||||
|
||||
if attr["IPAM"]["Config"]:
|
||||
if "Subnet" in attr["IPAM"]["Config"][0]:
|
||||
subnet = attr["IPAM"]["Config"][0]["Subnet"]
|
||||
if "Gateway" in attr["IPAM"]["Config"][0]:
|
||||
gateway = attr["IPAM"]["Config"][0]["Gateway"]
|
||||
|
||||
if len(attr["IPAM"]["Config"]) > 1:
|
||||
if "Subnet" in attr["IPAM"]["Config"][1]:
|
||||
subnetv6 = attr["IPAM"]["Config"][1]["Subnet"]
|
||||
if "Gateway" in attr["IPAM"]["Config"][1]:
|
||||
gatewayv6 = attr["IPAM"]["Config"][1]["Gateway"]
|
||||
|
||||
tmp = {
|
||||
"id": attr["Id"],
|
||||
"name": attr["Name"],
|
||||
"time": dp.convert_timezone_str_to_timestamp(attr["Created"]),
|
||||
"driver": attr["Driver"],
|
||||
"subnet": subnet,
|
||||
"gateway": gateway,
|
||||
"subnetv6": subnetv6,
|
||||
"gatewayv6": gatewayv6,
|
||||
"labels": attr["Labels"],
|
||||
"used": 1 if c_result["Containers"] else 0,
|
||||
"containers": c_result["Containers"],
|
||||
}
|
||||
data.append(tmp)
|
||||
|
||||
return public.return_message(0, 0, sorted(data, key=lambda x: x['time'], reverse=True))
|
||||
except Exception as e:
|
||||
err = str(e)
|
||||
if "Connection reset by peer" in err:
|
||||
return public.return_message(-1, 0, public.lang("The docker service is running abnormally, please restart and try again!"))
|
||||
return public.return_message(-1, 0, [])
|
||||
|
||||
def get_network_attr(self, networks):
|
||||
network = networks.list()
|
||||
return [i.attrs for i in network]
|
||||
|
||||
def add(self, get):
|
||||
"""
|
||||
:param name 网络名称
|
||||
:param driver bridge/ipvlan/macvlan/overlay
|
||||
:param options Driver options as a key-value dictionary
|
||||
:param subnet '124.42.0.0/16'
|
||||
:param gateway '124.42.0.254'
|
||||
:param iprange '124.42.0.0/24'
|
||||
:param labels Map of labels to set on the network. Default None.
|
||||
:param remarks 备注
|
||||
:param get:
|
||||
:return:
|
||||
"""
|
||||
# {"name": "23sdff223f", "driver": "overlay", "options": "", "subnet": "192.168.13.0/24",
|
||||
# "gateway": "192.168.13.1", "iprange": "192.168.13.0/24", "labels": ""}
|
||||
# 校验参数
|
||||
try:
|
||||
get.validate([
|
||||
Param('name').Require().String(),
|
||||
Param('subnet').Require(),
|
||||
Param('gateway').Require(),
|
||||
Param('iprange').Require(),
|
||||
], [
|
||||
public.validate.trim_filter(),
|
||||
])
|
||||
except Exception as ex:
|
||||
public.print_log("error info: {}".format(ex))
|
||||
return public.return_message(-1, 0, str(ex))
|
||||
|
||||
import docker
|
||||
|
||||
# 传参 给默认值
|
||||
subnet = get.get("subnet", "")
|
||||
gateway = get.get("gateway", "")
|
||||
iprange = get.get("iprange", "")
|
||||
subnet_v6 = get.get("subnet_v6", "")
|
||||
gateway_v6 = get.get("gateway_v6", "")
|
||||
v6_status = get.get("status/d", 0)
|
||||
|
||||
ipam_pool4 = docker.types.IPAMPool(
|
||||
subnet=subnet,
|
||||
gateway=gateway,
|
||||
iprange=iprange
|
||||
)
|
||||
|
||||
if v6_status != 0:
|
||||
ipam_pool6 = docker.types.IPAMPool(
|
||||
subnet=subnet_v6,
|
||||
gateway=gateway_v6,
|
||||
)
|
||||
ipam_config = docker.types.IPAMConfig(
|
||||
pool_configs=[ipam_pool4, ipam_pool6]
|
||||
)
|
||||
else:
|
||||
ipam_config = docker.types.IPAMConfig(
|
||||
pool_configs=[ipam_pool4]
|
||||
)
|
||||
|
||||
try:
|
||||
self.docker_client(self._url).networks.create(
|
||||
name=get.name,
|
||||
options=dp.set_kv(get.options),
|
||||
driver=get.driver, # 使用用户指定的网络驱动类型
|
||||
ipam=ipam_config,
|
||||
enable_ipv6=v6_status,
|
||||
)
|
||||
except docker.errors.APIError as e:
|
||||
print(str(e))
|
||||
if "failed to allocate gateway" in str(e):
|
||||
return public.return_message(-1, 0,
|
||||
public.lang("The gateway setting is wrong, Please enter a gateway that matches the subnet: {}", get.subnet))
|
||||
if "invalid CIDR address" in str(e):
|
||||
return public.return_message(-1, 0, public.lang("Subnet address format error, please enter for example: 172.16.0.0/16"))
|
||||
if "invalid Address SubPool" in str(e):
|
||||
return public.return_message(-1, 0,
|
||||
public.lang("IP range format error, please enter the appropriate IP range for this subnet:", get.subnet))
|
||||
if "Pool overlaps with other one on this address space" in str(e):
|
||||
return public.return_message(-1, 0, public.lang("IP range [ {}] already exists!", get.subnet))
|
||||
if "kernel version failed to meet the minimum ipvlan kernel requirement" in str(e):
|
||||
return public.return_message(-1, 0, public.lang("The system kernel version is too low, please update the kernel or choose another network mode"))
|
||||
if "not a swarm manager" in str(e):
|
||||
return public.return_message(-1, 0, public.lang("The current node is not a Swarm and needs to be configured before it can be used"))
|
||||
return public.return_message(-1, 0, public.lang("Failed to add network! {}", str(e)))
|
||||
|
||||
dp.write_log("Added network [{}] [{}] successful!".format(get.name, get.iprange))
|
||||
return public.return_message(0, 0, public.lang("Added network successfully!"))
|
||||
|
||||
def del_network(self, get):
|
||||
"""
|
||||
:param id
|
||||
:param get:
|
||||
:return:
|
||||
"""
|
||||
# 校验参数
|
||||
try:
|
||||
get.validate([
|
||||
Param('id').Require().String(),
|
||||
], [
|
||||
public.validate.trim_filter(),
|
||||
])
|
||||
except Exception as ex:
|
||||
public.print_log("error info: {}".format(ex))
|
||||
return public.return_message(-1, 0, str(ex))
|
||||
|
||||
try:
|
||||
networks = self.docker_client(self._url).networks.get(get.id)
|
||||
attrs = networks.attrs
|
||||
if attrs['Name'] in ["bridge", "none"]:
|
||||
return public.return_message(-1, 0, public.lang("The system default network cannot be deleted!"))
|
||||
|
||||
networks.remove()
|
||||
dp.write_log("Delete network [{}] successfully!".format(attrs['Name']))
|
||||
return public.return_message(0, 0, public.lang("successfully delete!"))
|
||||
|
||||
except docker.errors.APIError as e:
|
||||
if " has active endpoints" in str(e):
|
||||
return public.return_message(-1, 0, public.lang("The network cannot be deleted while it is in use!"))
|
||||
return public.return_message(-1, 0, public.lang("Delete failed! {}", str(e)))
|
||||
|
||||
def prune(self, get):
|
||||
"""
|
||||
删除无用的网络
|
||||
:param get:
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
res = self.docker_client(self._url).networks.prune()
|
||||
if not res['NetworksDeleted']:
|
||||
return public.return_message(-1, 0, public.lang("There are no useless networks!"))
|
||||
|
||||
dp.write_log("Delete useless network successfully!")
|
||||
return public.return_message(0, 0, public.lang("successfully delete!"))
|
||||
|
||||
except docker.errors.APIError as e:
|
||||
return public.return_message(-1, 0, public.lang("Delete failed! {}", str(e)))
|
||||
|
||||
def disconnect(self, get):
|
||||
"""
|
||||
断开某个容器的网络
|
||||
:param id
|
||||
:param container_id
|
||||
:param get:
|
||||
:return:
|
||||
"""
|
||||
# 校验参数
|
||||
try:
|
||||
get.validate([
|
||||
Param('id').Require().String(),
|
||||
Param('container_id').Require().String(),
|
||||
], [
|
||||
public.validate.trim_filter(),
|
||||
])
|
||||
except Exception as ex:
|
||||
public.print_log("error info: {}".format(ex))
|
||||
return public.return_message(-1, 0, str(ex))
|
||||
|
||||
try:
|
||||
get.id = get.get("id/s", "")
|
||||
get.container_id = get.get("container_id/s", "")
|
||||
if get.id == "":
|
||||
return public.return_message(-1, 0, public.lang("Network ID cannot be empty"))
|
||||
if get.container_id == "":
|
||||
return public.return_message(-1, 0, public.lang("Container ID cannot be empty"))
|
||||
|
||||
networks = self.docker_client(self._url).networks.get(get.id)
|
||||
networks.disconnect(get.container_id)
|
||||
dp.write_log("Network disconnection [{}] successful!".format(get.id))
|
||||
return public.return_message(0, 0, public.lang("Network disconnection was successful!"))
|
||||
except docker.errors.APIError as e:
|
||||
if "No such container" in str(e):
|
||||
return public.return_message(-1, 0, public.lang("Container ID: {}, does not exist!", get.container_id))
|
||||
if "network" in str(e) and "Not Found" in str(e):
|
||||
return public.return_message(-1, 0, public.lang("Network ID: {}, does not exist!", get.id))
|
||||
return public.return_message(-1, 0, public.lang("Network disconnection failed! {}", str(e)))
|
||||
|
||||
def connect(self, get):
|
||||
"""
|
||||
连接到指定网络
|
||||
:param id
|
||||
:param container_id
|
||||
:param get:
|
||||
:return:
|
||||
"""
|
||||
# 校验参数
|
||||
try:
|
||||
get.validate([
|
||||
Param('id').Require().String(),
|
||||
Param('container_id').Require().String(),
|
||||
], [
|
||||
public.validate.trim_filter(),
|
||||
])
|
||||
except Exception as ex:
|
||||
public.print_log("error info: {}".format(ex))
|
||||
return public.return_message(-1, 0, str(ex))
|
||||
|
||||
try:
|
||||
networks = self.docker_client(self._url).networks.get(get.id)
|
||||
networks.connect(get.container_id)
|
||||
dp.write_log("Network connection [{}] successful!".format(get.id))
|
||||
return public.return_message(0, 0, public.lang("Network connection successful!"))
|
||||
except docker.errors.APIError as e:
|
||||
if "No such container" in str(e):
|
||||
return public.return_message(-1, 0, public.lang("Container ID: {}, does not exist!", get.container_id))
|
||||
if "network" in str(e) and "Not Found" in str(e):
|
||||
return public.return_message(-1, 0, public.lang("Network ID: {}, does not exist!", get.id))
|
||||
return public.return_message(-1, 0, public.lang("Failed to connect to network! {}", str(e)))
|
||||
# 2024/11/27 14:37 创建网络
|
||||
def create_network(self, get):
|
||||
'''
|
||||
@name 创建网络
|
||||
'''
|
||||
get.subnet = get.get("subnet", "")
|
||||
get.gateway = get.get("gateway", "")
|
||||
get.iprange = get.get("iprange", "")
|
||||
get.subnet_v6 = get.get("subnet_v6", "")
|
||||
get.gateway_v6 = get.get("gateway_v6", "")
|
||||
get.v6_status = get.get("status", 0)
|
||||
|
||||
get.name = get.get("name", None)
|
||||
if get.name is None: return public.return_message(-1, 0, public.lang("The network name cannot be empty!"))
|
||||
|
||||
get.driver = get.get("driver", "bridge")
|
||||
get.options = get.get("options", "")
|
||||
|
||||
ipam_pool4 = {}
|
||||
ipam_pool6 = {}
|
||||
if get.subnet != "":
|
||||
if get.gateway == "": return public.return_message(-1, 0, public.lang("Gateways can't be empty!"))
|
||||
if get.iprange == "": return public.return_message(-1, 0, public.lang("IP ranges cannot be empty!"))
|
||||
|
||||
ipam_pool4 = {
|
||||
"subnet": get.subnet,
|
||||
"gateway": get.gateway,
|
||||
"iprange": get.iprange
|
||||
}
|
||||
|
||||
if get.v6_status != 0:
|
||||
ipam_pool6 = {
|
||||
"subnet": get.subnet_v6,
|
||||
"gateway": get.gateway_v6,
|
||||
}
|
||||
|
||||
if not ipam_pool4 and not ipam_pool6:
|
||||
get.ipam = None
|
||||
elif not ipam_pool6:
|
||||
get.ipam = {
|
||||
"Driver": "default",
|
||||
"Config": [{
|
||||
"Subnet": get.subnet,
|
||||
"Gateway": get.gateway,
|
||||
"IPRange": get.iprange
|
||||
}]
|
||||
}
|
||||
else:
|
||||
get.ipam = {
|
||||
"Driver": "default",
|
||||
"Config": [{
|
||||
"Subnet": get.subnet,
|
||||
"Gateway": get.gateway,
|
||||
"IPRange": get.iprange
|
||||
}, {
|
||||
"Subnet": get.subnet_v6,
|
||||
"Gateway": get.gateway_v6,
|
||||
}]
|
||||
}
|
||||
|
||||
get.post_data = {
|
||||
"name": get.name,
|
||||
"options": None,
|
||||
"driver": get.driver,
|
||||
"ipam": get.ipam,
|
||||
"enable_ipv6": bool(get.v6_status),
|
||||
}
|
||||
|
||||
from btdockerModelV2.dockerSock import network
|
||||
sk_network = network.dockerNetWork()
|
||||
create_network = sk_network.create_network(get)
|
||||
|
||||
if not create_network:
|
||||
return public.return_message(-1, 0, public.lang("Creating a network failed!"))
|
||||
if "message" in create_network:
|
||||
if "already exists" in create_network["message"]:
|
||||
return public.return_message(-1, 0, public.lang("Network name: [{}] already exists!".format(get.name)))
|
||||
return public.return_message(-1, 0, create_network["message"])
|
||||
return public.return_message(0, 0, public.lang("Create a network successfully!"))
|
||||
Reference in New Issue
Block a user