setHostingId($this->getWhmcsParamByKey("serviceid")); DB::beginTransaction(); try { foreach ($enteries as &$ip) { //insert to data base $ip->save(); $this->hosting()->ipAdd($ip->ip); //lock ip in proxmox addon if (!Utility::isIpManagerProxmoxVPSIntegration()) { IpAddress::where('ip', $ip->ip) ->update(["hosting_id" => $ip->hosting_id]); } } //update hosting $this->hosting()->save(); DB::commit(); } catch (\Exception $ex) { DB::rollBack(); throw $ex; } } /** * @param VmIpAddress[] $enteries */ public function addPrivate(array $enteries) { $this->setHostingId($this->getWhmcsParamByKey("serviceid")); $container = []; $rate = null; $tag = $this->makeTag(); if ($this->isWhmcsConfigOption(ConfigurableOption::NETWORK_RATE) && $this->getWhmcsConfigOption(ConfigurableOption::NETWORK_RATE) != "-1") { $rate = $this->getWhmcsConfigOption(ConfigurableOption::NETWORK_RATE); } else { if ($this->configuration()->getRate()) { $rate = $this->configuration()->getRate(); } } //cloud init $isCloudInit = $this->configuration()->isQemu() && $this->configuration()->isCloudInit(); try { DB::beginTransaction(); Api::beginTransaction(); foreach ($enteries as &$ip) { //insert to data base $ip->save(); $this->hosting()->ipAdd($ip->ip); //lock ip in proxmox addon IpAddress::where('ip', $ip->ip) ->update(["hosting_id" => $ip->hosting_id]); $networkId = $this->vm()->findFreeNetworDeviceId(); if ($this->configuration()->isLxc()) { $networkDevice = new NetworkDeviceLxc('net' . $networkId); $networkDevice->setName('eth' . $networkId) ->setBridge($this->configuration()->getPrivateBridge()) ->setFirewall($this->configuration()->isNetworkFirewall() ? 1 : 0); if ($ip->mac_address && $ip->mac_address != "auto") { $networkDevice->setHwaddr($ip->mac_address); } $networkDevice->setIp($ip->ip) ->setCidr($ip->cidr) ->setGw($ip->gateway) ->setTag($tag) ->setRate($rate) ->setTrunks($ip->trunks); $container[$networkDevice->getId()] = $networkDevice->asConfig(); } else { if ($this->configuration()->isQemu()) { $networkDevice = new NetworkDeviceKvm('net' . $networkId); $networkDevice->setBridge($this->configuration()->getPrivateBridge()) ->setModel($this->configuration()->getNetworkPrivateModel()) ->setRate($rate) ->setTag($tag) ->setTrunks($ip->trunks) ->setFirewall($this->configuration()->isNetworkFirewall() ? 1 : 0); if ($ip->mac_address && $ip->mac_address != "auto") { $networkDevice->setMacAddress($ip->mac_address); } $container[$networkDevice->getId()] = $networkDevice->asConfig(); if ($isCloudInit) { $ipConfig = new IpConfig('ipconfig' . $networkId); $ipConfig->setIp(trim($ip->ip)) ->setCidr(trim($ip->cidr)) ->setGw(trim($ip->gateway)); $container[$ipConfig->getId()] = $ipConfig->asConfig(); } } } $ip->net = $networkDevice->getId(); $ip->tag = $tag; $ip->save(); } //update hosting $this->hosting()->save(); $this->vm()->updateConfig($container); DB::commit(); } catch (\Exception $ex) { DB::rollBack(); Api::commit(); throw $ex; } } protected function makeTag() { if (is_numeric($this->getWhmcsCustomField(CustomField::TAG))) { return $this->getWhmcsCustomField(CustomField::TAG); } if (!$this->configuration()->getTagFrom() && !$this->configuration()->getTagTo()) { return null; } $tag = $this->nextTag(); if (!$tag) { throw new \Exception("Max VLAN tag have been reached, Please Configure product (Max VLAN tag)"); } $this->customFieldUpdate("VLAN Tag", $tag); return $tag; } public function nextTag() { $cf = "tblcustomfields"; $cv = "tblcustomfieldsvalues"; for ($i = $this->configuration()->getTagFrom(); $i <= $this->configuration()->getTagTo(); $i++) { $query = DB::table($cf) ->select("{$cv}.value") ->leftJoin($cv, "{$cv}.fieldid", "=", "{$cf}.id") ->where("{$cf}.type", "product") ->where("{$cf}.relid", $this->getWhmcsParamByKey("packageid")) ->where("{$cf}.fieldname", 'like', "VLAN Tag%") ->where("{$cv}.relid", '!=', $this->getWhmcsParamByKey("serviceid")) ->where("{$cv}.value", $i); if ($query->count()) { continue; } return $i; } return false; } /** * @return VmIpAddress */ public function getPrivateIpAddress() { $ip = IpAddress::where('private', 1) ->where('type', 'IPv4') ->whereIn("sid", [$this->getWhmcsParamByKey('serverid'), "0"]) ->where('hosting_id', '0') ->firstOrFail(); $newIp = new VmIpAddress(); $newIp->fill($ip->toArray()); $newIp->hosting_id = $this->getWhmcsParamByKey("serviceid"); $newIp->server_id = $this->getWhmcsParamByKey("serverid"); return $newIp; } public function hasPrivateIpAddress() { $query = IpAddress::where('private', 1) ->where('type', 'IPv4') ->whereIn("sid", [$this->getWhmcsParamByKey('serverid'), "0"]) ->where('hosting_id', '0'); return $query->count(); } public function deleteByNetworkId(array $networkIds) { if (is_null($networkIds)) { throw new \InvalidArgumentException('The network ids cannot be empty'); } $ipAddresses = VmIpAddress::ofHostingId($this->getWhmcsParamByKey("serviceid")) ->whereIn("net", $networkIds)->get()->all(); return $this->deleteByIpAddresses($ipAddresses); } public function deleteByIpAddresses(array $ipAddresses) { if (is_null($ipAddresses)) { throw new \InvalidArgumentException('The IP Addresses cannot be empty'); } $devices = $this->vm()->getNetworkDevices(); if($this->configuration()->getPrivateBridge()){ $privateDevices = $this->vm()->getNetworkDevices($this->configuration()->getPrivateBridge()); } $configDelete = []; $ipunassigned = []; $this->setHostingId($this->getWhmcsParamByKey("serviceid")); DB::beginTransaction(); Api::beginTransaction(); try { foreach ($ipAddresses as &$ip) { if (is_numeric($ip)) { $ip = VmIpAddress::where("id", $ip)->firstOrFail(); } if (!$ip instanceof VmIpAddress) { throw new \InvalidArgumentException(sprintf('The following class are not supported "%s"', get_class($ip))); }; //privateĀ ip if(!$this->deletePrivateNetwork && isset($privateDevices[0]) && $privateDevices[0] && $privateDevices[0]->getId() == $ip->net){ continue; } $ip->delete(); $this->hosting()->ipDelete($ip->ip); $ipunassigned[] = $ip->ip; //Unlock ip in Proxmox Addon IpAddress::where('ip', $ip->ip) ->where('hosting_id', $ip->hosting_id) ->update(["hosting_id" => "0", 'last_check' => Utility::timeStamp()]); foreach ($devices as $deviceIndex => $device) { if ($this->configuration()->isOneNetworkDevice() && $device->getId() == "net0") { continue; } if($device instanceof NetworkDeviceLxc) { if ($ip->ip == $device->getIp()) { $device->setIp(null); } if ($ip->ip == $device->getIp6()) { $device->setIp6(null); } if(empty($device->getIp6()) && empty($device->getIp())) { unset($devices[$deviceIndex]); $configDelete[] = $device->getId(); } } elseif($device instanceof NetworkDeviceKvm && $ip->net && $ip->net == $device->getId()) { $configDelete[] = $device->getId(); unset($devices[$deviceIndex]); } } //cloud init if ($this->vm() instanceof Kvm) { foreach ($this->vm()->getIpConfig()->fetch() as $ipConfig) { if ($ipConfig->getIp() == $ip->ip || $ipConfig->getIp6() == $ip->ip) { $configDelete[] = $ipConfig->getId(); } } } } $this->hosting()->save(); /** * Update current config. We need that only if we remove only one IP and other IP is still on the same interface */ $config = new Config(); $config->setNet($devices); $config = $config->toArray(); if($config) { $this->vm()->updateConfig($config); } /** * Delete config. We need that when there is no more network interface */ if (!empty($configDelete)) { $this->vm()->deleteConfig(implode(",", $configDelete)); } if(!empty( $ipunassigned)){ (new IpLogService())->unassigned($ipunassigned); } DB::commit(); } catch (\Exception $ex) { DB::rollBack(); Api::commit(); throw $ex; } } public function hasIp($totalIpv4, $totalIpv6, $nodeName, $bridge="") { $virtualization = $this->configuration()->isQemu() ? "KVM" : "LXC"; $tags = $this->configuration()->getTags(); if($this->getWhmcsConfigOption(ConfigurableOption::TAG) > 0){ $tags = [$this->getWhmcsConfigOption(ConfigurableOption::TAG)]; } if ((int)$totalIpv4 > 0) { /** * @var $ipCollections IpAddress */ $ipCollections = IpAddress::where('hosting_id', '0') ->where('private', '0') ->where('type', 'IPv4') ->whereIn('sid', [$this->getWhmcsParamByKey('serverid'), '0']) ->whereIn('visualization', [$virtualization, 'Auto']) ->whereIn('node', [$nodeName, '0', ""]) ->whereIn('bridge', [$bridge, ""]); //tag if ($tags) { $ipCollections->ofTags($tags); } $count = $ipCollections->count(); if ((int)$count < $totalIpv4) { $errorMessage = sprintf("Unable to get %s of IPv4. IP Addresses available: %s", $totalIpv4, $count); if($nodeName){ $errorMessage = sprintf("Unable to get %s of IPv4, on node: %s. IP Addresses available: %s", $totalIpv4, $nodeName, $count); } throw new \Exception($errorMessage); } } if ((int)$totalIpv6 > 0) { $ipCollections = IpAddress::where('hosting_id', '0') ->where('private', '0') ->where('type', 'IPv6') ->whereIn('sid', [$this->getWhmcsParamByKey('serverid'), '0']) ->whereIn('visualization', [$virtualization, 'Auto']) ->whereIn('node', [$nodeName, '0', ""]) ->whereIn('bridge', [$bridge, ""]); //tag if ($tags) { $ipCollections->ofTags($tags); } $count = $ipCollections->count(); if ((int)$count < $totalIpv6) { $errorMessage = sprintf("Unable to get %s of IPv6. IP Addresses available: %s", $totalIpv6, $count); if($nodeName){ $errorMessage = sprintf("Unable to get %s of IPv6, on node: %s. IP Addresses available: %s", $totalIpv6, $nodeName, $count); } throw new \Exception($errorMessage); } } return $this; } public function addIp($totalIpv4, $totalIpv6, $nodeName, $bridge="") { try { DB::beginTransaction(); $virtualization = $this->configuration()->isQemu() ? "KVM" : "LXC"; $this->setHostingId($this->getWhmcsParamByKey('serviceid')); $tags = $this->configuration()->getTags(); if($this->getWhmcsConfigOption(ConfigurableOption::TAG) > 0){ $tags = [$this->getWhmcsConfigOption(ConfigurableOption::TAG)]; } if ((int)$totalIpv4 > 0) { $query = IpAddress::where('hosting_id', '0') ->where('private', '0') ->where('type', 'IPv4') ->whereIn('sid', [$this->getWhmcsParamByKey('serverid'), '0']) ->whereIn('visualization', [$virtualization, 'Auto']) ->whereIn('node', [$nodeName, '0', ""]) ->whereIn('bridge', [$bridge, ""]); if ($tags) { $query->ofTags($tags); } $count = $query->limit($totalIpv4) ->orderBy('last_check', 'asc') ->update(["hosting_id" => $this->getWhmcsParamByKey('serviceid'), 'last_check' => Utility::timeStamp()]); if ((int)$count < $totalIpv4) { throw new \Exception(sprintf("Unable to get %s of IPv4. IP Addresses available: %s", $totalIpv4, $count)); } } if ((int)$totalIpv6 > 0) { $query = IpAddress::where('hosting_id', '0') ->where('private', '0') ->where('type', 'IPv6') ->whereIn('sid', [$this->getWhmcsParamByKey('serverid'), '0']) ->whereIn('visualization', [$virtualization, 'Auto']) ->whereIn('node', [$nodeName, '0', ""]) ->whereIn('bridge', [$bridge, ""]); if ($tags) { $query->ofTags($tags); } $count = $query->limit($totalIpv6) ->orderBy('last_check', 'asc') ->update(["hosting_id" => $this->getWhmcsParamByKey('serviceid'), 'last_check' => Utility::timeStamp()]); if ((int)$count < $totalIpv6) { throw new \Exception(sprintf("Unable to get %s of IPv6. IP Addresses available: %s", $totalIpv6, $count)); } } $vmIp = (new VmIpAddress())->getTable(); $collection = IpAddress::where('hosting_id', $this->getWhmcsParamByKey('serviceid')) ->orderBy("ip", "desc") ->whereNotIn('ip', function ($query) use ($vmIp) { $query->select('ip')->from($vmIp); }); $newIps = []; foreach ($collection->get()->sortBy("type")->all() as $ip) { /*@var $ip IpAddress */ $newIp = new VmIpAddress(); $ipData = $ip->toArray(); unset($ipData['id']); $ipData['hosting_id'] = $this->getWhmcsParamByKey('serviceid'); $ipData['server_id'] = $this->getWhmcsParamByKey('serverid'); $newIp->fill($ipData)->save(); $this->hosting()->ipAdd($ip->ip); $newIps[] = $ip->ip; } if(!empty($newIps)){ (new IpLogService())->assigned($newIps); } $this->hosting()->save(); DB::commit(); } catch (\Exception $ex) { DB::rollBack(); throw $ex; } } public function deleteIpAddresses() { $ipunassigned = VmIpAddress::ofHostingId($this->getWhmcsParamByKey('serviceid'))->pluck('ip')->toArray(); if(!empty( $ipunassigned)){ (new IpLogService())->unassigned($ipunassigned); } VmIpAddress::ofHostingId($this->getWhmcsParamByKey('serviceid'))->delete(); //Unlock ip in Proxmox Addon IpAddress::where('hosting_id', $this->getWhmcsParamByKey('serviceid')) ->update(["hosting_id" => "0", 'last_check' => Utility::timeStamp()]); $this->setHostingId($this->getWhmcsParamByKey('serviceid')); $this->hosting()->dedicatedip = ""; $this->hosting()->assignedips = ""; $this->hosting()->save(); return $this; } public function buildLxc() { $container = []; /** * @var VmIpAddress[] $ipv4 */ $ipv4 = VmIpAddress::ofHostingId($this->getWhmcsParamByKey("serviceid")) ->ofIp4() ->ofNetNull() ->get(); //ip6 $ipv6 = VmIpAddress::ofHostingId($this->getWhmcsParamByKey("serviceid")) ->ofIp6() ->ofNetNull() ->get(); //Network $bridge = $this->configuration()->getBridge(); $firewall = $this->configuration()->isNetworkFirewall() ? 1 : 0; $ip4Mode = $this->configuration()->getIpv4NetworkMode(); $ip6Mode = $this->configuration()->getIpv6NetworkMode(); $rate = null; if ($this->getWhmcsConfigOption(ConfigurableOption::NETWORK_RATE, $this->configuration()->getRate()) && $this->getWhmcsConfigOption(ConfigurableOption::NETWORK_RATE, $this->configuration()->getRate()) != "-1") { $rate = $this->getWhmcsConfigOption(ConfigurableOption::NETWORK_RATE, $this->configuration()->getRate()); } $networkId = 0; if ($this->hasVm()) { $networkId = $this->vm()->findFreeNetworDeviceId(); } for ($i = 0; $i <= 9; $i++) { //Empty IP Addresses if (!$ipv4->get($i) && !$ipv6->get($i)) { break; } if ($networkId > 9) { break; } $mac = null; //Name $interface = new NetworkDeviceLxc('net' . $networkId); $interface->setName('eth' . $networkId) ->setBridge($bridge) ->setFirewall($firewall); //IP 4 if ($ipv4->get($i)) { if ($ipv4->get($i)->mac_address) { $mac = $ipv4->get($i)->mac_address; } if ($ipv4->get($i)->tag) { $interface->setTag($ipv4->get($i)->tag); } $interface->setTrunks($ipv4->get($i)->trunks); if ($ip4Mode == 'static') { //IP & CIRD $interface->setIp($ipv4->get($i)->ip); $interface->setCidr($ipv4->get($i)->cidr); //Gateway $interface->setGw($ipv4->get($i)->gateway); } $ipv4->get($i)->net = $interface->getId(); $ipv4->get($i)->save(); } if ($ip4Mode == "dhcp") { $interface->setIp("dhcp"); } //IP 6 if ($ip6Mode == "dhcp") { $interface->setIp6("dhcp"); } else { if ($ip6Mode == "slaac") { $interface->setIp6("auto"); } } if ($ipv6->get($i)) { //IP & CIRD if ($ip6Mode == "static") { $interface->setIp6($ipv6->get($i)->ip); $interface->setCidr6($ipv6->get($i)->cidr); //Gateway $interface->setGw6($ipv6->get($i)->gateway); } if ($ipv6->get($i)->tag) { $interface->setTag($ipv6->get($i)->tag); } if ($ipv6->get($i)->trunks) { $interface->setTrunks($ipv6->get($i)->trunks); } if ($mac == null && $ipv6->get($i)->mac_address) { $mac = $ipv6->get($i)->mac_address; } $ipv6->get($i)->net = $interface->getId(); $ipv6->get($i)->save(); } if ($rate) { $interface->setRate($rate); } $interface->setHwaddr($mac); $container['net' . $networkId] = $interface->asConfig(); $networkId++; } return $container; } public function buildQemu() { $container = []; /** * @var VmIpAddress[] $ipv4 */ $ipv4 = VmIpAddress::ofHostingId($this->getWhmcsParamByKey("serviceid")) ->ofIp4() ->ofNetNull() ->get(); //ip6 $ipv6 = VmIpAddress::ofHostingId($this->getWhmcsParamByKey("serviceid")) ->ofIp6() ->ofNetNull() ->get(); //Network $model = $this->configuration()->getNetworkModel(); $bridge = $this->configuration()->getBridge(); $firewall = $this->configuration()->isNetworkFirewall() ? 1 : 0; $rate = null; if ($this->getWhmcsConfigOption(ConfigurableOption::NETWORK_RATE, $this->configuration()->getRate()) && $this->getWhmcsConfigOption(ConfigurableOption::NETWORK_RATE, $this->configuration()->getRate()) != "-1") { $rate = $this->getWhmcsConfigOption(ConfigurableOption::NETWORK_RATE, $this->configuration()->getRate()); } $networkId = 0; $vmNetworkDevices = []; if ($this->hasVm()) { $networkId = $this->vm()->findFreeNetworDeviceId(); $vmNetworkDevices = $this->vm()->getNetworkDevices(); } $i4 = 0; $i6 = 0; $isApi52 = version_compare($this->api()->getVersion(), "5.2", '>='); for ($i = 0; $i <= 31; $i++) { //Empty IP Addresses if (!$ipv4->get($i4) && !$ipv6->get($i6)) { break; } if ($networkId > 31) { break; } if ($this->configuration()->isOneNetworkDevice() && ($i > 0 || count($vmNetworkDevices))) { VmIpAddress::ofHostingId($this->getWhmcsParamByKey("serviceid")) ->ofNetNull() ->update(["net" => 'net0']); break; } $mac = null; $isIp4 = false; //Name $interface = new NetworkDeviceKvm('net' . $networkId); $interface->setModel($model) ->setBridge($bridge) ->setFirewall($firewall); $ipConfig = new IpConfig('ipconfig' . $networkId); //IP 4 if ($ipv4->get($i4)) { $isIp4 = true; if (trim($ipv4->get($i4)->mac_address)) { $mac = $ipv4->get($i4)->mac_address; } if ($ipv4->get($i4)->tag) { $interface->setTag(trim($ipv4->get($i4)->tag)); } $interface->setTrunks(trim($ipv4->get($i4)->trunks)); //private ip if($this->configuration()->getPrivateBridge() && IpAddress::ofHostingId($this->getWhmcsParamByKey("serviceid"))->ofIp($ipv4->get($i4)->ip)->private()->count()){ $interface->setBridge($this->configuration()->getPrivateBridge()); } $ipConfig->setIp(trim($ipv4->get($i4)->ip)); $ipConfig->setCidr(trim($ipv4->get($i4)->cidr)); //Gateway $ipConfig->setGw(trim($ipv4->get($i4)->gateway)); $ipv4->get($i4)->net = $interface->getId(); $ipv4->get($i4)->save(); $i4++; } //ipv6 if ($ipv6->get($i6) && (!$isIp4 || $interface->getTag() == $ipv6->get($i6)->tag)) { //IP & CIRD $ipConfig->setIp6(trim($ipv6->get($i6)->ip)); $ipConfig->setCidr6(trim($ipv6->get($i6)->cidr)); //Gateway $ipConfig->setGw6(trim($ipv6->get($i6)->gateway)); if ($ipv6->get($i6)->tag) { $tag = $ipv6->get($i6)->tag; $interface->setTag(trim($ipv6->get($i6)->tag)); } if ($ipv6->get($i6)->trunks) { $interface->setTrunks(trim($ipv6->get($i6)->trunks)); } if ($mac == null && $ipv6->get($i6)->mac_address) { $mac = $ipv6->get($i6)->mac_address; } $ipv6->get($i6)->net = $interface->getId(); $ipv6->get($i6)->save(); $i6++; } $interface->setRate(trim($rate)); $interface->setMacAddress(trim($mac)); $interface->setQueues(trim($this->configuration()->getQueues())); $container[$interface->getId()] = $interface->asConfig(); if ($isApi52 && ($ipConfig->getIp() || $ipConfig->getIp6())) { $container[$ipConfig->getId()] = $ipConfig->asConfig(); } $networkId++; } return $container; } public function unassignIpAddressesAndDeleteNetwork() { list($requestIPv4, $requestIPv6) = $this->getIpAddressesRequest(); $ip4 = []; $ip6 = []; if ($requestIPv4 < 0) { $ip4 = VmIpAddress::ofHostingId($this->getWhmcsParamByKey('serviceid')) ->ofIp4() ->ofNetNotNull() ->limit(abs($requestIPv4)) ->orderByIdDesc() ->get() ->all(); } if ($requestIPv6 < 0) { $ip6 = VmIpAddress::ofHostingId($this->getWhmcsParamByKey('serviceid')) ->ofIp6() ->ofNetNotNull() ->limit(abs($requestIPv6)) ->orderByIdDesc() ->get() ->all(); } $ipAddresses = array_merge($ip4, $ip6); if (!empty($ipAddresses)) { $this->deleteByIpAddresses($ipAddresses); } } public function getIpAddressesRequest() { $ipv4Used = (int)VmIpAddress::ofHostingId($this->getWhmcsParamByKey('serviceid')) ->ofIp4() ->count(); $ipv6Used = (int)VmIpAddress::ofHostingId($this->getWhmcsParamByKey('serviceid')) ->ofIp6() ->count(); $requestIPv4 = (int)$this->configuration()->getIpv4(); $requestIPv6 = (int)$this->configuration()->getIpv6(); if ($this->isWhmcsConfigOption(ConfigurableOption::IPV4)) { $requestIPv4 = (int)$this->getWhmcsConfigOption(ConfigurableOption::IPV4); } if ($this->isWhmcsConfigOption(ConfigurableOption::IPV6)) { $requestIPv6 = (int)$this->getWhmcsConfigOption(ConfigurableOption::IPV6); } return [(int)$requestIPv4 -= $ipv4Used, (int)$requestIPv6 -= $ipv6Used]; } /** * @param bool $deletePrivateNetwork * @return NetworkService */ public function setDeletePrivateNetwork(bool $deletePrivateNetwork): NetworkService { $this->deletePrivateNetwork = $deletePrivateNetwork; return $this; } }