| |
| |
| |
| |
| |
| |
| |
| |
|
|
| import docker.errors |
| |
| |
| |
| import public |
|
|
| from btdockerModel import dk_public as dp |
| from btdockerModel.dockerBase import dockerBase |
|
|
|
|
| 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 [] |
|
|
| 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 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.returnMsg(False, "docker服务运行异常,请尝试重启docker后再试!") |
| return [] |
|
|
| 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: |
| """ |
| 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.returnMsg(False, "网关设置有误,请输入与此子网相符的网关:{}".format(get.subnet)) |
| if "invalid CIDR address" in str(e): |
| return public.returnMsg(False, "子网地址格式错误,请输入例如:172.16.0.0/16") |
| if "invalid Address SubPool" in str(e): |
| return public.returnMsg(False, "IP范围格式错误,请输入与此子网相符的IP范围:{}".format(get.subnet)) |
| if "Pool overlaps with other one on this address space" in str(e): |
| return public.returnMsg(False, "IP范围【{}】已经存在!".format(get.subnet)) |
| if "kernel version failed to meet the minimum ipvlan kernel requirement" in str(e): |
| return public.returnMsg(False, "你的系统内核版本低于 4.2,不满足ipvlan对内核版本的最小要求,请更新内核或选择其他网络模式") |
| if "not a swarm manager" in str(e): |
| return public.returnMsg(False, "当前节点不是 Swarm 管理节点。需要进行相关配置后才能使用。") |
| return public.returnMsg(False, "添加网络失败! {}".format(str(e))) |
|
|
| dp.write_log("添加网络 [{}] [{}] 成功!".format(get.name, get.iprange)) |
| return public.returnMsg(True, "添加网络成功!") |
|
|
| def del_network(self, get): |
| """ |
| :param id |
| :param get: |
| :return: |
| """ |
| try: |
| networks = self.docker_client(self._url).networks.get(get.id) |
| attrs = networks.attrs |
| if attrs['Name'] in ["bridge", "none"]: |
| return public.returnMsg(False, "系统默认网络不能被删除!") |
|
|
| networks.remove() |
| dp.write_log("删除网络 [{}] 成功!".format(attrs['Name'])) |
| return public.returnMsg(True, "删除成功!") |
|
|
| except docker.errors.APIError as e: |
| if " has active endpoints" in str(e): |
| return public.returnMsg(False, "网络正在被使用中无法被删除!") |
| return public.returnMsg(False, "删除失败! {}".format(str(e))) |
|
|
| def prune(self, get): |
| """ |
| 删除无用的网络 |
| :param get: |
| :return: |
| """ |
| try: |
| res = self.docker_client(self._url).networks.prune() |
| if not res['NetworksDeleted']: |
| return public.returnMsg(False, "没有无用的网络!") |
|
|
| dp.write_log("删除无用的网络成功!") |
| return public.returnMsg(True, "删除成功!") |
|
|
| except docker.errors.APIError as e: |
| return public.returnMsg(False, "删除失败! {}".format(str(e))) |
|
|
| def disconnect(self, get): |
| """ |
| 断开某个容器的网络 |
| :param id |
| :param container_id |
| :param get: |
| :return: |
| """ |
| try: |
| get.id = get.get("id/s", "") |
| get.container_id = get.get("container_id/s", "") |
| if get.id == "": |
| return public.returnMsg(False, "网络ID不能为空,请传入有效的网络ID!") |
| if get.container_id == "": |
| return public.returnMsg(False, "容器ID不能为空,请传入有效的容器ID!") |
|
|
| networks = self.docker_client(self._url).networks.get(get.id) |
| networks.disconnect(get.container_id) |
| dp.write_log("断开网络 [{}] 成功!".format(get.id)) |
| return public.returnMsg(True, "断开网络成功!") |
| except docker.errors.APIError as e: |
| if "No such container" in str(e): |
| return public.returnMsg(False, "容器ID: {}, 不存在!".format(get.container_id)) |
| if "network" in str(e) and "Not Found" in str(e): |
| return public.returnMsg(False, "网络ID: {}, 不存在!".format(get.id)) |
| return public.returnMsg(False, "断开网络失败! {}".format(str(e))) |
|
|
| def connect(self, get): |
| """ |
| 连接到指定网络 |
| :param id |
| :param container_id |
| :param get: |
| :return: |
| """ |
| try: |
| networks = self.docker_client(self._url).networks.get(get.id) |
| networks.connect(get.container_id) |
| dp.write_log("连接网络 [{}] 成功!".format(get.id)) |
| return public.returnMsg(True, "连接网络成功!") |
| except docker.errors.APIError as e: |
| if "No such container" in str(e): |
| return public.returnMsg(False, "容器ID: {}, 不存在!".format(get.container_id)) |
| if "network" in str(e) and "Not Found" in str(e): |
| return public.returnMsg(False, "网络ID: {}, 不存在!".format(get.id)) |
| return public.returnMsg(False, "连接网络失败! {}".format(str(e))) |
|
|
| |
| 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.returnResult(False, "网络名称不能为空!") |
|
|
| get.driver = get.get("driver", "bridge") |
| get.options = get.get("options", "") |
|
|
| ipam_pool4 = {} |
| ipam_pool6 = {} |
| if get.subnet != "": |
| if get.gateway == "": return public.returnResult(False, "网关不能为空!") |
| if get.iprange == "": return public.returnResult(False, "IP范围不能为空!") |
|
|
| 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 btdockerModel.dockerSock import network |
| sk_network = network.dockerNetWork() |
| create_network = sk_network.create_network(get) |
|
|
| if not create_network: |
| return public.returnResult(False, "创建网络失败!") |
| if "message" in create_network: |
| if "already exists" in create_network["message"]: |
| return public.returnResult(False, "网络名称:【{}】 已存在!".format(get.name)) |
| return public.returnResult(False, create_network["message"]) |
| return public.returnResult(True, "创建网络成功!") |
|
|