Advertisement
NMamaev

Untitled

Apr 13th, 2023
47
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.13 KB | None | 0 0
  1. #!/usr/bin/python3
  2.  
  3. import argparse
  4. import json
  5. import logging
  6. import sys
  7. from xml.etree import ElementTree
  8.  
  9. import libvirt
  10. from common import coloredlog, consul_utils, remote, const
  11. from kvm_utils import domain as h_domain, guest_agent
  12. from kvm_utils import virt
  13. from vm_firewall import vm_firewall_factory as h_firewall
  14. from vm_firewall.vm_firewall_common import make_vm_firewall_params
  15.  
  16.  
  17. def main():
  18.     coloredlog.set_logger('network_configure')
  19.     consul = consul_utils.Consul()
  20.     result = {}
  21.     parser = argparse.ArgumentParser(description='Create host')
  22.     parser.add_argument('--private-key', metavar='private_key')
  23.     parser.add_argument('--node_port', type=int)
  24.     parser.add_argument('--node_addr')
  25.     parser.add_argument('--internal_name')
  26.     args = parser.parse_args()
  27.     params = json.load(sys.stdin)
  28.     metadata = json.loads(params['metadata'])
  29.  
  30.     conn = libvirt.open('qemu+tls://' + args.node_addr + '/system')
  31.     domain = h_domain.Domain(consul, conn, args.internal_name)
  32.  
  33.     logging.info('Start network configure for domain %s' % args.internal_name)
  34.     logging.debug(f'With params: {json.dumps(params)}')
  35.  
  36.     node = remote.ServerNode(args.node_addr, args.node_port, args.private_key)
  37.     tuned_resources = params['host']['tuned_resources']
  38.  
  39.     vm_firewall_params = make_vm_firewall_params(
  40.         tuned_resources["network"],
  41.         tuned_resources["anti_spoofing"],
  42.         tuned_resources["anti_spoofing_settings"],
  43.         tuned_resources.get('tcp_connections_in'),
  44.         tuned_resources.get('tcp_connections_out'),
  45.         tuned_resources.get('firewall_rules')
  46.     )
  47.     with h_firewall.make_vm_firewall(node, args.internal_name, params['node']['os_version'],
  48.                                      vm_firewall_params) as firewall:
  49.         firewall.setup(metadata)
  50.  
  51.     with node:
  52.         execute_type = h_domain.ExecuteType.VIRT_CUSTOMIZE
  53.  
  54.         ip_automation = const.IpAutomationType(params['host'].get('ip_automation', 'none'))
  55.         if params['host']['ga_enabled']:
  56.             execute_type = h_domain.ExecuteType.GUEST_AGENT
  57.  
  58.         if execute_type == h_domain.ExecuteType.VIRT_CUSTOMIZE:
  59.             if ip_automation is not const.IpAutomationType.NONE:
  60.                 domain.stop()
  61.         else:
  62.             domain.start(params['ha_enabled'])
  63.             guest_agent.wait_ga_start(node, args.internal_name)
  64.  
  65.         domain_settings = h_domain.make_domain_setting(execute_type, node, args.internal_name,
  66.                                                        params['host']['os_group'], ip_automation)
  67.         domain_settings.configure_network(args.internal_name, params['host']['network'], params['datacenter_type'],
  68.                                           params['host']['dns_servers'])
  69.         if params["datacenter_type"] == const.DatacenterType.IP_FABRIC.value:
  70.             Router(node, params).update()
  71.  
  72.     libvirt_domain = conn.lookupByName(args.internal_name)
  73.     domain_xml = ElementTree.fromstring(virt.get_domain_xml(libvirt_domain))
  74.     virt.save_domain_xml(conn, domain_xml, metadata)
  75.  
  76.     if domain.was_active:
  77.         domain.start(params['ha_enabled'])
  78.  
  79.     logging.debug('Result: %s' % result)
  80.     json.dump(result, sys.stdout)
  81.  
  82.  
  83. def is_invalid_ip(iface_id: int, ip: dict) -> bool:
  84.     return iface_id != ip['interface_id'] or ip['state'] in ['crashed', 'deleting']
  85.  
  86.  
  87. class Router:
  88.     def __init__(self, node: remote.ServerNode, params):
  89.         # на текущий момент работает по полной аналогии с хуком qemu
  90.         # TODO(truenya) metadata не самый надежный источник, здесь было бы лучше работать с xml домена, как в VM-11040
  91.         self.metadata = json.loads(params['metadata'])
  92.         self.host_params = params['host']
  93.         self.node = node
  94.  
  95.     def update(self):
  96.         for index, host_iface in enumerate(self.metadata['interfaces']):
  97.             gateways = []
  98.             if host_iface.get("is_vxlan"):
  99.                 continue
  100.             iface_name = f"vm{self.metadata['id']}_net{index}"
  101.             if "deleted_ip_addr" in self.host_params:
  102.                 self._process_deleting_ip(iface_id=host_iface['id'], iface_name=iface_name)
  103.             else:
  104.                 self._process_adding_ipv4(gateways=gateways, iface_id=host_iface['id'], iface_name=iface_name)
  105.                 self._process_adding_ipv6(gateways=gateways, iface_id=host_iface['id'], iface_name=iface_name)
  106.  
  107.     def _process_adding_ipv4(self, gateways, iface_id, iface_name):
  108.         for ip in self.metadata['ipv4']:
  109.             if is_invalid_ip(iface_id, ip):
  110.                 continue
  111.             ip_addr = ip['ip_addr']
  112.             if ip_addr in self.host_params["new_ip_addrs"]:
  113.                 gateway = ip["gateway"]
  114.                 if gateway not in gateways:
  115.                     gateways.append(gateway)
  116.                     self.node.run(f'ip addr add {gateway} dev {iface_name}')
  117.                 self.node.run(f'ip r add {ip_addr} dev {iface_name} scope link')
  118.  
  119.     def _process_adding_ipv6(self, gateways, iface_id, iface_name):
  120.         for ip in self.metadata['ipv6']:
  121.             if is_invalid_ip(iface_id, ip):
  122.                 continue
  123.             ip_addr = ip['ip_addr']
  124.             if ip_addr in self.host_params["new_ip_addrs"]:
  125.                 gateway = ip["gateway"]
  126.  
  127.                 if 'block_prefix' in ip:
  128.                     gateway += f'/{ip["block_prefix"]}'
  129.  
  130.                 if gateway not in gateways:
  131.                     gateways.append(gateway)
  132.                     self.node.run(f'ip addr add {gateway} dev {iface_name}')
  133.                 self.node.run(f'ip r add {ip_addr} dev {iface_name} scope link')
  134.  
  135.     def _process_deleting_ip(self, iface_id, iface_name):
  136.         ip_to_delete = self.host_params["deleted_ip_addr"]
  137.  
  138.         def is_target_ip(ip) -> bool:
  139.             return iface_id == ip['interface_id'] and ip_to_delete == ip['ip_addr']
  140.  
  141.         for ip in filter(is_target_ip, self.metadata['ipv4'] + self.metadata['ipv6']):
  142.             self.node.run(f'ip r del {ip["ip_addr"]} dev {iface_name}')
  143.  
  144.  
  145. if __name__ == '__main__':
  146.     main()
  147.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement