Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python3
- import argparse
- import json
- import logging
- import sys
- from xml.etree import ElementTree
- import libvirt
- from common import coloredlog, consul_utils, remote, const
- from kvm_utils import domain as h_domain, guest_agent
- from kvm_utils import virt
- from vm_firewall import vm_firewall_factory as h_firewall
- from vm_firewall.vm_firewall_common import make_vm_firewall_params
- def main():
- coloredlog.set_logger('network_configure')
- consul = consul_utils.Consul()
- result = {}
- parser = argparse.ArgumentParser(description='Create host')
- parser.add_argument('--private-key', metavar='private_key')
- parser.add_argument('--node_port', type=int)
- parser.add_argument('--node_addr')
- parser.add_argument('--internal_name')
- args = parser.parse_args()
- params = json.load(sys.stdin)
- metadata = json.loads(params['metadata'])
- conn = libvirt.open('qemu+tls://' + args.node_addr + '/system')
- domain = h_domain.Domain(consul, conn, args.internal_name)
- logging.info('Start network configure for domain %s' % args.internal_name)
- logging.debug(f'With params: {json.dumps(params)}')
- node = remote.ServerNode(args.node_addr, args.node_port, args.private_key)
- tuned_resources = params['host']['tuned_resources']
- vm_firewall_params = make_vm_firewall_params(
- tuned_resources["network"],
- tuned_resources["anti_spoofing"],
- tuned_resources["anti_spoofing_settings"],
- tuned_resources.get('tcp_connections_in'),
- tuned_resources.get('tcp_connections_out'),
- tuned_resources.get('firewall_rules')
- )
- with h_firewall.make_vm_firewall(node, args.internal_name, params['node']['os_version'],
- vm_firewall_params) as firewall:
- firewall.setup(metadata)
- with node:
- execute_type = h_domain.ExecuteType.VIRT_CUSTOMIZE
- ip_automation = const.IpAutomationType(params['host'].get('ip_automation', 'none'))
- if params['host']['ga_enabled']:
- execute_type = h_domain.ExecuteType.GUEST_AGENT
- if execute_type == h_domain.ExecuteType.VIRT_CUSTOMIZE:
- if ip_automation is not const.IpAutomationType.NONE:
- domain.stop()
- else:
- domain.start(params['ha_enabled'])
- guest_agent.wait_ga_start(node, args.internal_name)
- domain_settings = h_domain.make_domain_setting(execute_type, node, args.internal_name,
- params['host']['os_group'], ip_automation)
- domain_settings.configure_network(args.internal_name, params['host']['network'], params['datacenter_type'],
- params['host']['dns_servers'])
- if params["datacenter_type"] == const.DatacenterType.IP_FABRIC.value:
- Router(node, params).update()
- libvirt_domain = conn.lookupByName(args.internal_name)
- domain_xml = ElementTree.fromstring(virt.get_domain_xml(libvirt_domain))
- virt.save_domain_xml(conn, domain_xml, metadata)
- if domain.was_active:
- domain.start(params['ha_enabled'])
- logging.debug('Result: %s' % result)
- json.dump(result, sys.stdout)
- def is_invalid_ip(iface_id: int, ip: dict) -> bool:
- return iface_id != ip['interface_id'] or ip['state'] in ['crashed', 'deleting']
- class Router:
- def __init__(self, node: remote.ServerNode, params):
- # на текущий момент работает по полной аналогии с хуком qemu
- # TODO(truenya) metadata не самый надежный источник, здесь было бы лучше работать с xml домена, как в VM-11040
- self.metadata = json.loads(params['metadata'])
- self.host_params = params['host']
- self.node = node
- def update(self):
- for index, host_iface in enumerate(self.metadata['interfaces']):
- gateways = []
- if host_iface.get("is_vxlan"):
- continue
- iface_name = f"vm{self.metadata['id']}_net{index}"
- if "deleted_ip_addr" in self.host_params:
- self._process_deleting_ip(iface_id=host_iface['id'], iface_name=iface_name)
- else:
- self._process_adding_ipv4(gateways=gateways, iface_id=host_iface['id'], iface_name=iface_name)
- self._process_adding_ipv6(gateways=gateways, iface_id=host_iface['id'], iface_name=iface_name)
- def _process_adding_ipv4(self, gateways, iface_id, iface_name):
- for ip in self.metadata['ipv4']:
- if is_invalid_ip(iface_id, ip):
- continue
- ip_addr = ip['ip_addr']
- if ip_addr in self.host_params["new_ip_addrs"]:
- gateway = ip["gateway"]
- if gateway not in gateways:
- gateways.append(gateway)
- self.node.run(f'ip addr add {gateway} dev {iface_name}')
- self.node.run(f'ip r add {ip_addr} dev {iface_name} scope link')
- def _process_adding_ipv6(self, gateways, iface_id, iface_name):
- for ip in self.metadata['ipv6']:
- if is_invalid_ip(iface_id, ip):
- continue
- ip_addr = ip['ip_addr']
- if ip_addr in self.host_params["new_ip_addrs"]:
- gateway = ip["gateway"]
- if 'block_prefix' in ip:
- gateway += f'/{ip["block_prefix"]}'
- if gateway not in gateways:
- gateways.append(gateway)
- self.node.run(f'ip addr add {gateway} dev {iface_name}')
- self.node.run(f'ip r add {ip_addr} dev {iface_name} scope link')
- def _process_deleting_ip(self, iface_id, iface_name):
- ip_to_delete = self.host_params["deleted_ip_addr"]
- def is_target_ip(ip) -> bool:
- return iface_id == ip['interface_id'] and ip_to_delete == ip['ip_addr']
- for ip in filter(is_target_ip, self.metadata['ipv4'] + self.metadata['ipv6']):
- self.node.run(f'ip r del {ip["ip_addr"]} dev {iface_name}')
- if __name__ == '__main__':
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement