def getBestStack(self, gid, imageId=None, excludelist=[], memory=None, routeros=False): capacityinfo = self.getCapacityInfo(gid, imageId) if not capacityinfo: raise exceptions.ServiceUnavailable("No available node") capacityinfo = [ node for node in capacityinfo if node["id"] not in excludelist ] if not capacityinfo: raise exceptions.ServiceUnavailable( "No available node with specified resources") if routeros: capacityinfo.sort(key=lambda k: k["usedros"]) for provider in capacityinfo: if memory is None: return provider elif memory < provider["freememory"]: return provider raise exceptions.ServiceUnavailable( "No available node with specified resources")
def _getVFWObject(self, fwid): try: fwobj = self.osisvfw.get(fwid) except: raise exceptions.ServiceUnavailable( "VFW with id %s is not deployed yet!" % fwid) if not fwobj.nid: raise exceptions.ServiceUnavailable( "VFW with id %s is not deployed yet!" % fwid) return fwobj
def fw_delete(self, fwid, deletemodel=True, timeout=600, **kwargs): """ param:fwid firewall id param:gid grid id """ fwobj = self.osisvfw.get(fwid) args = {"name": "%s_%s" % (fwobj.domain, fwobj.name)} if fwobj.type == "routeros": args = {"networkid": fwobj.id} if fwobj.nid: job = self.cb.executeJumpscript( "jumpscale", "vfs_destroy_routeros", nid=fwobj.nid, gid=fwobj.gid, args=args, timeout=timeout, ) if job["state"] != "OK": raise exceptions.ServiceUnavailable( "Failed to remove vfw with id %s" % fwid) if deletemodel: # delete backup if the delete is final args = { "ovs_connection": self.get_ovs_connection(fwobj.gid), "diskpath": "/routeros/{0:04x}/routeros-small-{0:04x}.raw".format( fwobj.id), } job = self.cb.executeJumpscript( "greenitglobe", "deletedisk_by_path", role="storagedriver", gid=fwobj.gid, args=args, ) if job["state"] != "OK": raise exceptions.ServiceUnavailable( "Failed to remove vfw with id %s" % fwid) if deletemodel: self.osisvfw.delete(fwid) else: result = self.cb.executeJumpscript("jumpscale", "vfs_delete", nid=fwobj.nid, gid=fwobj.gid, args=args)["result"] if result: self.osisvfw.delete(fwid) return result
def getNextEdgeClient(self, vpool, edgeclients=None): clients = edgeclients or self.edgeclients[:] clients = filter(lambda x: x['vpool'] == vpool, clients) if not clients: raise exceptions.ServiceUnavailable( "No storagerouter available for vpool {}".format(vpool)) return sorted(clients, key=lambda client: client['vdiskcount'])[0]
def fw_stop(self, fwid, **kwargs): """ param:fwid firewall id param:gid grid id """ fwobj = self._getVFWObject(fwid) args = {"networkid": fwobj.id} if fwobj.type == "routeros": job = self.cb.executeJumpscript( "jumpscale", "vfs_stop_routeros", gid=fwobj.gid, nid=fwobj.nid, args=args, ) else: job = self.cb.executeJumpscript("jumpscale", "vfs_stop", gid=fwobj.gid, nid=fwobj.nid, args=args) if job["state"] != "OK": raise exceptions.ServiceUnavailable("Failed to stop vfw") return job["result"]
def fw_migrate(self, fwobj, sourceip, targetNid, **kwargs): args = { "networkid": fwobj.id, "vlan": fwobj.vlan, "externalip": fwobj.pubips[0], "sourceip": sourceip, } job = self.cb.executeJumpscript("jumpscale", "vfs_migrate_routeros", nid=targetNid, gid=fwobj.gid, args=args) if job["state"] != "OK": raise exceptions.ServiceUnavailable( "Failed to move routeros check job %(guid)s" % job) if job["result"]: args = {"networkid": fwobj.id, "domainxml": job["result"]} self.cb.executeJumpscript( "greenitglobe", "cleanup_network", nid=fwobj.nid, gid=fwobj.gid, args=args, ) fwobj.nid = targetNid self.osisvfw.set(fwobj) return job["result"]
def fw_check(self, fwid, timeout=60, **kwargs): """ will do some checks on firewall to see is running, is reachable over ssh, is connected to right interfaces param:fwid firewall id param:gid grid id """ fwobj = self._getVFWObject(fwid) args = {'networkid': fwobj.id} if fwobj.type == 'routeros': job = self.cb.executeJumpscript('jumpscale', 'vfs_checkstatus_routeros', gid=fwobj.gid, nid=fwobj.nid, args=args, timeout=timeout) else: job = self.cb.executeJumpscript('jumpscale', 'vfs_checkstatus', gid=fwobj.gid, nid=fwobj.nid, args=args) if job['state'] != 'OK': raise exceptions.ServiceUnavailable("Failed to get vfw status") return job['result']
def updateByPort(self, cloudspaceId, sourcePublicIp, sourcePublicPort, sourceProtocol, publicIp, publicPort, machineId, localPort, protocol=None, **kwargs): protocol = protocol or 'tcp' cloudspace, machine, fw, publicIp = self._validate_forward( cloudspaceId, publicIp, publicPort, machineId, localPort, protocol) fw_id, fw_gid = self._getFirewallId(cloudspaceId) if not self.netmgr.fw_check(fw_id, timeout=5): raise exceptions.ServiceUnavailable( 'Can not update PortForward at this time') forwards = self.netmgr.fw_forward_list(fw_id, fw_gid) for fw in forwards: if fw['publicIp'] == sourcePublicIp and int(fw['publicPort']) == sourcePublicPort and \ fw['protocol'] == sourceProtocol: forwards.remove(fw) break if self._selfcheckduplicate(forwards, publicIp, publicPort, protocol): raise exceptions.Conflict( "Forward for %s with port %s already exists" % (publicIp, publicPort)) self._deleteByPort(cloudspaceId, sourcePublicIp, sourcePublicPort, sourceProtocol) return self.create(cloudspaceId, publicIp, publicPort, machineId, localPort, protocol)
def fw_migrate(self, fwobj, sourceip, targetNid, **kwargs): args = { 'networkid': fwobj.id, 'vlan': fwobj.vlan, 'externalip': fwobj.pubips[0], 'sourceip': sourceip } job = self.cb.executeJumpscript('jumpscale', 'vfs_migrate_routeros', nid=targetNid, gid=fwobj.gid, args=args) if job['state'] != 'OK': raise exceptions.ServiceUnavailable( "Failed to move routeros check job %(guid)s" % job) if job['result']: args = {'networkid': fwobj.id, 'domainxml': job['result']} self.cb.executeJumpscript('greenitglobe', 'cleanup_network', nid=fwobj.nid, gid=fwobj.gid, args=args) fwobj.nid = targetNid self.osisvfw.set(fwobj) return job['result']
def fw_delete(self, fwid, deletemodel=True, timeout=600, **kwargs): """ param:fwid firewall id param:gid grid id """ fwobj = self.osisvfw.get(fwid) args = {'name': '%s_%s' % (fwobj.domain, fwobj.name)} if fwobj.type == 'routeros': args = {'networkid': fwobj.id} if fwobj.nid: job = self.cb.executeJumpscript('jumpscale', 'vfs_destroy_routeros', nid=fwobj.nid, gid=fwobj.gid, args=args, timeout=timeout) if job['state'] != 'OK': raise exceptions.ServiceUnavailable( "Failed to remove vfw with id %s" % fwid) if deletemodel: # delete backup if the delete is final args = { 'ovs_connection': self.get_ovs_connection(fwobj.gid), 'diskpath': '/routeros/{0:04x}/routeros-small-{0:04x}.raw'.format( fwobj.id) } job = self.cb.executeJumpscript('greenitglobe', 'deletedisk_by_path', role='storagedriver', gid=fwobj.gid, args=args) if job['state'] != 'OK': raise exceptions.ServiceUnavailable( "Failed to remove vfw with id %s" % fwid) if deletemodel: self.osisvfw.delete(fwid) else: result = self.cb.executeJumpscript('jumpscale', 'vfs_delete', nid=fwobj.nid, gid=fwobj.gid, args=args)['result'] if result: self.osisvfw.delete(fwid) return result
def chooseStack(self, machine): if models.disk.count({'id': {'$in': machine.disks}, 'type': 'P'}) == 0: cloudspace = models.cloudspace.get(machine.cloudspaceId) newstack = self.getBestStack(cloudspace.gid, machine.imageId, memory=machine.memory) if newstack == -1: raise exceptions.ServiceUnavailable('Not enough resources available to start the requested machine') machine.stackId = newstack['id'] models.vmachine.set(machine) return True
def create( self, cloudspaceId, publicIp, publicPort, machineId, localPort, protocol=None, **kwargs ): """ Create a port forwarding rule :param cloudspaceId: id of the cloudspace :param publicIp: public ipaddress :param publicPort: public port :param machineId: id of the virtual machine :param localPort: local port on vm :param protocol: protocol udp or tcp """ cloudspace, machine, fw, publicIp = self._validate_forward( cloudspaceId, publicIp, publicPort, machineId, localPort, protocol ) fw_id = fw["guid"] if not self.netmgr.fw_check(fw_id, timeout=5): raise exceptions.ServiceUnavailable( "Can not create PortForward at this time" ) grid_id = fw["gid"] localIp = self._getLocalIp(machine) forwards = self.netmgr.fw_forward_list(fw_id, cloudspace.gid) if self._selfcheckduplicate(forwards, publicIp, publicPort, protocol): raise exceptions.Conflict( "Forward to %s with port %s already exists" % (publicIp, publicPort) ) try: result = self.netmgr.fw_forward_create( fw_id, grid_id, publicIp, publicPort, localIp, localPort, protocol ) except: raise exceptions.ServiceUnavailable( "Forward to %s with port %s failed to create." % (publicIp, publicPort) ) return result
def getStackAndProvider(newstackId): provider = None try: if not newstackId: stack = self.cb.getBestStack(cloudspace.gid, imageId, excludelist, machine.memory) if stack == -1: raise exceptions.ServiceUnavailable( 'Not enough resources available to provision the requested machine') provider = self.cb.getProviderByStackId(stack['id']) else: activesessions = self.cb.getActiveSessionsKeys() provider = self.cb.getProviderByStackId(newstackId) if (provider.gid, provider.id) not in activesessions: raise exceptions.ServiceUnavailable( 'Not enough resources available to provision the requested machine') except: self.cleanup(machine, cloudspace.gid, volumes) raise return provider
def fw_get_openvpn_config(self, fwid, **kwargs): fwobj = self._getVFWObject(fwid) args = {'fwobject': fwobj.obj2dict()} job = self.cb.executeJumpscript('jumpscale', 'vfs_get_openvpn_config_routeros', gid=fwobj.gid, nid=fwobj.nid, args=args) if job['state'] != 'OK': raise exceptions.ServiceUnavailable("Failed to get OpenVPN Config") return job['result']
def update(self, cloudspaceId, id, publicIp, publicPort, machineId, localPort, protocol, **kwargs): """ Update a port forwarding rule :param cloudspaceId: id of the cloudspace :param id: id of the portforward to edit :param publicIp: public ipaddress :param publicPort: public port :param machineId: id of the virtual machine :param localPort: local port :param protocol: protocol udp or tcp """ machineId = int(machineId) cloudspaceId = int(cloudspaceId) cloudspace = self.models.cloudspace.get(cloudspaceId) fw = self.netmgr.fw_list(cloudspace.gid, cloudspaceId) if len(fw) == 0: raise exceptions.NotFound( 'Incorrect cloudspace or there is no corresponding gateway') fw_id = fw[0]['guid'] if not self.netmgr.fw_check(fw_id, timeout=5): raise exceptions.ServiceUnavailable( 'Can not update PortForward at this time') forwards = self.netmgr.fw_forward_list(fw_id, cloudspace.gid) id = int(id) if not id < len(forwards): raise exceptions.NotFound('Cannot find the rule with id %s' % str(id)) forward = forwards[id] machine = self.models.vmachine.get(machineId) if machine.nics: if machine.nics[0].ipAddress != 'Undefined': localIp = machine.nics[0].ipAddress else: raise exceptions.NotFound( 'No correct ipaddress found for machine with id %s' % machineId) self.netmgr.fw_forward_delete(fw_id, cloudspace.gid, forward['publicIp'], forward['publicPort'], forward['localIp'], forward['localPort'], forward['protocol']) forwards = self.netmgr.fw_forward_list(fw_id, cloudspace.gid) if self._selfcheckduplicate(forwards, publicIp, publicPort, protocol): raise exceptions.Conflict( "Forward for %s with port %s already exists" % (publicIp, publicPort)) self.netmgr.fw_forward_create(fw_id, cloudspace.gid, publicIp, publicPort, localIp, localPort, protocol) forwards = self.netmgr.fw_forward_list(fw_id, cloudspace.gid) return self._process_list(forwards, cloudspaceId)
def _deleteByPort(self, cloudspaceId, publicIp, publicPort, proto, **kwargs): fw_id, fw_gid = self._getFirewallId(cloudspaceId) if not self.netmgr.fw_check(fw_id, timeout=5): raise exceptions.ServiceUnavailable( 'Can not delete PortForward at this time') if not self.netmgr.fw_forward_delete( fw_id, fw_gid, publicIp, publicPort, protocol=proto): raise exceptions.NotFound( "Could not find port forwarding with %s:%s %s" % (publicIp, publicPort, proto)) forwards = self.netmgr.fw_forward_list(fw_id, fw_gid) return self._process_list(forwards, cloudspaceId)
def chooseStack(self, machine): if models.disk.count({"id": {"$in": machine.disks}, "type": "P"}) == 0: cloudspace = models.cloudspace.get(machine.cloudspaceId) newstack = self.getBestStack(cloudspace.gid, machine.imageId, memory=machine.memory) if newstack == -1: raise exceptions.ServiceUnavailable( "Not enough resources available to start the requested machine" ) machine.stackId = newstack["id"] models.vmachine.set(machine) return True
def fw_remove_lease(self, fwid, macaddress): fwobj = self._getVFWObject(fwid) args = {'fwobject': fwobj.obj2dict(), 'macaddress': macaddress} job = self.cb.executeJumpscript('jumpscale', 'vfs_remove_lease_routeros', gid=fwobj.gid, nid=fwobj.nid, args=args) if job['state'] != 'OK': raise exceptions.ServiceUnavailable( "Failed to release lease for macaddress %s. Error: %s" % (macaddress, job['result']['errormessage'])) return job['result']
def fw_get_openvpn_config(self, fwid, **kwargs): fwobj = self._getVFWObject(fwid) args = {"fwobject": fwobj.obj2dict()} job = self.cb.executeJumpscript( "jumpscale", "vfs_get_openvpn_config_routeros", gid=fwobj.gid, nid=fwobj.nid, args=args, ) if job["state"] != "OK": raise exceptions.ServiceUnavailable("Failed to get OpenVPN Config") return job["result"]
def fw_start(self, fwid, resettype='restore', targetNid=None, **kwargs): """ param:fwid firewall id param:gid grid id """ if resettype not in ['factory', 'restore']: raise exceptions.BadRequest( "Invalid value {} for resettype".format(resettype)) try: running = self.fw_check(fwid) except: running = False if running: return True fwobj = self._getVFWObject(fwid) cloudspace = self.cbmodel.cloudspace.get(int(fwobj.domain)) if cloudspace.externalnetworkip is None: raise exceptions.BadRequest( 'Can not reset VFW which has no external network IP please deploy instead.' ) if resettype == 'restore': restored = self.fw_restore(fwid, targetNid) if resettype == 'factory' or not restored: pool = self.cbmodel.externalnetwork.get( cloudspace.externalnetworkId) externalipaddress = netaddr.IPNetwork(cloudspace.externalnetworkip) publicgw = pool.gateway publiccidr = externalipaddress.prefixlen password = str(uuid.uuid4()) self.fw_create(fwobj.gid, fwobj.domain, password, fwobj.pubips[0], 'routeros', fwobj.id, publicgw, publiccidr, pool.vlan, targetNid, cloudspace.privatenetwork) fwobj = self._getVFWObject(fwid) # to get updated model args = {'fwobject': fwobj.obj2dict()} if fwobj.type == 'routeros': job = self.cb.executeJumpscript('jumpscale', 'vfs_start_routeros', gid=fwobj.gid, nid=fwobj.nid, args=args) else: job = self.cb.executeJumpscript('jumpscale', 'vfs_start', gid=fwobj.gid, nid=fwobj.nid, args=args) if job['state'] != 'OK': raise exceptions.ServiceUnavailable("Failed to start vfw") self.fw_reapply(fwid) return job['result']
def fw_restore(self, fwid, targetNid=None, **kwargs): fwobj = self.osisvfw.get(fwid) if targetNid: fwobj.nid = targetNid self.osisvfw.set(fwobj) args = {'networkid': fwobj.id} job = self.cb.executeJumpscript('jumpscale', 'vfs_routeros_restore', nid=fwobj.nid, gid=fwobj.gid, args=args) if job['state'] != 'OK': raise exceptions.ServiceUnavailable("Failed to restore vfw") return job['result']
def fw_restore(self, fwid, targetNid=None, **kwargs): fwobj = self.osisvfw.get(fwid) if targetNid: fwobj.nid = targetNid self.osisvfw.set(fwobj) args = {"networkid": fwobj.id} job = self.cb.executeJumpscript("jumpscale", "vfs_routeros_restore", nid=fwobj.nid, gid=fwobj.gid, args=args) if job["state"] != "OK": raise exceptions.ServiceUnavailable("Failed to restore vfw") return job["result"]
def _move_virtual_machines(self, stack, title, ctx, stackmachines, exclude_vfwid=None): machines_actor = j.apps.cloudbroker.machine othernodes = self.scl.node.search({ "gid": stack["gid"], "status": "ENABLED", "roles": "fw" })[1:] if not othernodes: raise exceptions.ServiceUnavailable( "There is no other Firewall node available to move the Virtual Firewall to" ) for machine in stackmachines: ctx.events.sendMessage( title, "Moving Virtual Machine %s" % machine["name"]) try: machines_actor.moveToDifferentComputeNode( machine["id"], reason="Disabling source", force=True) except Exception as e: j.errorconditionhandler.processPythonExceptionObject(e) vfws = self._vcl.search({ "gid": stack["gid"], "nid": int(stack["referenceId"]), "id": { "$ne": exclude_vfwid }, })[1:] for vfw in vfws: nid = int( self.cb.getBestStack(stack["gid"], excludelist=[stack["id"]], memory=128)["referenceId"]) ctx.events.sendMessage(title, "Moving Virtual Firewal %s" % vfw["id"]) if not self.cb.netmgr.fw_move(vfw["guid"], nid): try: self.cb.netmgr.fw_delete(fwid=vfw["guid"], deletemodel=False, timeout=20) except exceptions.ServiceUnavailable: # agent on node is probably not running lets just start it somewhere else pass self.cb.netmgr.fw_start(vfw["guid"], targetNid=nid)
def delete(self, cloudspaceId, id, **kwargs): """ Delete a specific port forwarding rule :param cloudspaceId: id of the cloudspace :param id: id of the port forward rule """ try: result = self._delete(int(cloudspaceId), id) except exceptions.BaseError: raise except: raise exceptions.ServiceUnavailable("Failed to remove Portforwarding") return result
def fw_remove_lease(self, fwid, macaddress): fwobj = self._getVFWObject(fwid) args = {"fwobject": fwobj.obj2dict(), "macaddress": macaddress} job = self.cb.executeJumpscript( "jumpscale", "vfs_remove_lease_routeros", gid=fwobj.gid, nid=fwobj.nid, args=args, ) if job["state"] != "OK": raise exceptions.ServiceUnavailable( "Failed to release lease for macaddress %s. Error: %s" % (macaddress, job["result"]["errormessage"])) return job["result"]
def deleteByPort(self, cloudspaceId, publicIp, publicPort, proto=None, **kwargs): """ Delete a specific port forwarding rule by public port details :param cloudspaceId: id of the cloudspace :param publicIp: port forwarding public ip :param publicPort: port forwarding public port :param proto: port forwarding protocol """ try: self._deleteByPort(int(cloudspaceId), publicIp, publicPort, proto) except exceptions.BaseError: raise except: raise exceptions.ServiceUnavailable("Failed to remove Portforwarding") return True
def _delete(self, cloudspaceId, id, **kwargs): fw_id, fw_gid = self._getFirewallId(cloudspaceId) if not self.netmgr.fw_check(fw_id, timeout=5): raise exceptions.ServiceUnavailable( 'Can not delete PortForward at this time') forwards = self.netmgr.fw_forward_list(fw_id, fw_gid) id = int(id) if not id < len(forwards): raise exceptions.NotFound('Cannot find the rule with id %s' % str(id)) forward = forwards[id] self.netmgr.fw_forward_delete(fw_id, fw_gid, forward['publicIp'], forward['publicPort'], forward['localIp'], forward['localPort'], forward['protocol']) forwards = self.netmgr.fw_forward_list(fw_id, fw_gid) return self._process_list(forwards, cloudspaceId)
def _applyconfig(self, gid, nid, args): if args["fwobject"]["type"] == "routeros": job = self.cb.executeJumpscript("jumpscale", "vfs_applyconfig_routeros", gid=gid, nid=nid, args=args) else: job = self.cb.executeJumpscript("jumpscale", "vfs_applyconfig", gid=gid, nid=nid, args=args) if job["state"] != "OK": raise exceptions.ServiceUnavailable("Failed to apply config") return job["result"]
def _applyconfig(self, gid, nid, args): if args['fwobject']['type'] == 'routeros': job = self.cb.executeJumpscript('jumpscale', 'vfs_applyconfig_routeros', gid=gid, nid=nid, args=args) else: job = self.cb.executeJumpscript('jumpscale', 'vfs_applyconfig', gid=gid, nid=nid, args=args) if job['state'] != 'OK': raise exceptions.ServiceUnavailable('Failed to apply config') return job['result']
def fw_set_password(self, fwid, username, password): fwobj = self._getVFWObject(fwid) args = { 'fwobject': fwobj.obj2dict(), 'username': username, 'password': password } job = self.cb.executeJumpscript('jumpscale', 'vfs_set_password_routeros', gid=fwobj.gid, nid=fwobj.nid, args=args) if job['state'] != 'OK': raise exceptions.ServiceUnavailable( "Failed to set password. Error: %s" % (job['result']['errormessage'])) return job['result']