def assign_ip_addr(self, org_id, user_id): network_hash = self.server.network_hash server_id = self.server.id response = self.collection.update({ 'network': network_hash, 'server_id': server_id, 'user_id': {'$exists': False}, }, {'$set': { 'org_id': org_id, 'user_id': user_id, }}) if response['updatedExisting']: return network = ipaddress.IPv4Network(self.server.network) if self.server.network_start: network_start = ipaddress.IPv4Address(self.server.network_start) else: network_start = None if self.server.network_end: network_end = ipaddress.IPv4Address(self.server.network_end) else: network_end = None ip_pool = self.get_ip_pool(network, network_start) if not ip_pool: return try: doc = self.collection.find({ 'network': network_hash, 'server_id': server_id, }).sort('_id', pymongo.DESCENDING)[0] if doc: last_addr = doc['_id'] for remote_ip_addr in ip_pool: if int(remote_ip_addr) == last_addr: break except IndexError: pass for remote_ip_addr in ip_pool: if network_end and remote_ip_addr > network_end: break try: self.collection.insert({ '_id': int(remote_ip_addr), 'network': network_hash, 'server_id': server_id, 'org_id': org_id, 'user_id': user_id, 'address': '%s/%s' % (remote_ip_addr, network.prefixlen), }) return True except pymongo.errors.DuplicateKeyError: pass return False
def assign_ip_pool(self, network, network_start, network_end, network_hash): server_id = self.server.id pool_end = False network = ipaddress.IPv4Network(network) if network_start: network_start = ipaddress.IPv4Address(network_start) if network_end: network_end = ipaddress.IPv4Address(network_end) ip_pool = self.get_ip_pool(network, network_start) if not ip_pool: return bulk = self.collection.initialize_unordered_bulk_op() bulk_empty = True for org in self.server.iter_orgs(): org_id = org.id for user in org.iter_users(include_pool=True): try: remote_ip_addr = next(ip_pool) if network_end and remote_ip_addr > network_end: raise StopIteration() except StopIteration: pool_end = True break doc_id = int(remote_ip_addr) spec = { '_id': doc_id, } doc = {'$set': { '_id': doc_id, 'network': network_hash, 'server_id': server_id, 'org_id': org_id, 'user_id': user.id, 'address': '%s/%s' % (remote_ip_addr, network.prefixlen), }} if bulk: bulk.find(spec).upsert().update(doc) bulk_empty = False else: self.collection.update(spec, doc, upsert=True) if pool_end: logger.warning('Failed to assign ip addresses ' + 'to server, ip pool empty', 'server', server_id=server_id, org_id=org_id, ) break if not bulk_empty: bulk.execute()
def get_ip_pool(self, network, network_start): ip_pool = network.iterhosts() if network_start: network_start = ipaddress.IPv4Address(network_start) network_break = network_start - 1 while True: try: ip_addr = ip_pool.next() except StopIteration: logger.error('Failed to find network start', 'server', server_id=self.server.id, ) return if ip_addr == network_break: break else: ip_pool.next() return ip_pool
def assign_ip_pool_org(self, org_id): org = organization.get_by_id(org_id) network_hash = self.server.network_hash server_id = self.server.id org_id = org.id ip_pool_avial = True pool_end = False network = ipaddress.IPv4Network(self.server.network) network_start = self.server.network_start network_end = self.server.network_end if network_start: network_start = ipaddress.IPv4Address(network_start) if network_end: network_end = ipaddress.IPv4Address(network_end) ip_pool = self.get_ip_pool(network, network_start) if not ip_pool: return try: doc = self.collection.find({ 'network': network_hash, 'server_id': server_id, }).sort('_id', pymongo.DESCENDING)[0] if doc: last_addr = doc['_id'] for remote_ip_addr in ip_pool: if int(remote_ip_addr) == last_addr: break if network_end and remote_ip_addr > network_end: break except IndexError: pass if mongo.has_bulk: bulk = self.collection.initialize_unordered_bulk_op() bulk_empty = True else: bulk = None bulk_empty = None for user in org.iter_users(include_pool=True): if ip_pool_avial: response = self.collection.update( { 'network': network_hash, 'server_id': server_id, 'user_id': { '$exists': False }, }, {'$set': { 'org_id': org_id, 'user_id': user.id, }}) if response['updatedExisting']: continue ip_pool_avial = False try: remote_ip_addr = ip_pool.next() if network_end and remote_ip_addr > network_end: raise StopIteration() except StopIteration: pool_end = True break doc_id = int(remote_ip_addr) spec = { '_id': doc_id, } doc = { '$set': { '_id': doc_id, 'network': network_hash, 'server_id': server_id, 'org_id': org_id, 'user_id': user.id, 'address': '%s/%s' % (remote_ip_addr, network.prefixlen), } } if bulk: bulk.find(spec).upsert().update(doc) bulk_empty = False else: self.collection.update(spec, doc, upsert=True) if bulk and not bulk_empty: bulk.execute() if pool_end: logger.warning( 'Failed to assign ip addresses ' + 'to org, ip pool empty', 'server', org_id=org_id, )
def _upgrade_server(server_id, server_path): servers_db = get_collection('servers') servers_ip_pool_db = get_collection('servers_ip_pool') server_conf_path = os.path.join(server_path, 'server.conf') dh_param_path = os.path.join(server_path, 'dh_param.pem') ip_pool_path = os.path.join(server_path, 'ip_pool') spec = { '_id': bson.ObjectId(server_id), } update_doc = { 'lzo_compression': False, 'dns_servers': [], 'protocol': None, 'links': [], 'primary_organization': None, 'instances': [], 'port': None, 'network': None, 'dh_params': None, 'local_networks': [], 'primary_user': None, 'status': ONLINE, 'debug': False, 'cipher': 'bf128', 'bind_address': None, 'organizations': [], 'start_timestamp': datetime.datetime.fromtimestamp(0), 'instances_count': 0, 'name': None, 'search_domain': None, 'replica_count': 1, 'ca_certificate': None, 'dh_param_bits': None, 'mode': None, 'otp_auth': False, 'jumbo_frames': False, 'tls_auth': False, 'tls_auth_key': None, 'multi_device': False, 'hosts': [ settings.local.host_id, ], } with open(server_conf_path, 'r') as conf_file: for line in conf_file.readlines(): line = line.strip() name, value = line.split('=', 1) if name in ( 'primary_user', 'primary_organization', ): update_doc[name] = bson.ObjectId(value) if name in ( 'name', 'protocol', 'network', 'public_address', ): update_doc[name] = value elif name in ( 'port', 'dh_param_bits', ): update_doc[name] = int(value) if value else None elif name in ( 'lzo_compression', 'otp_auth', 'debug', ): update_doc[name] = True if value == 'true' else False elif name in ( 'organizations', 'dns_servers', 'debug', ): update_doc[name] = value.split(',') if value else [] elif name == 'mode': if value == 'all_traffic': update_doc[name] = ALL_TRAFFIC elif value == 'local_traffic': update_doc[name] = LOCAL_TRAFFIC elif value == 'vpn_traffic': update_doc[name] = VPN_TRAFFIC if os.path.exists(dh_param_path): with open(dh_param_path, 'r') as dh_param_file: update_doc['dh_params'] = dh_param_file.read().strip() if os.path.exists(ip_pool_path): with open(ip_pool_path, 'r') as ip_pool_file: ip_pool_data = json.loads(ip_pool_file.read()) network = ip_pool_data['network'] network_prefixlen = network.split('/')[1] for key, value in ip_pool_data.iteritems(): if key == 'network': continue org_id, user_id = key.split('-') address, _ = value.split('-') address_int = int(ipaddress.IPv4Address(address)) servers_ip_pool_db.update({ '_id': address_int, }, { '_id': address_int, 'server_id': server_id, 'user_id': user_id, 'org_id': org_id, 'network': network, 'address': address + '/' + network_prefixlen, }, upsert=True) servers_db.update(spec, update_doc, upsert=True)