Migrates Apex to Python
[apex.git] / apex / virtual / virtual_utils.py
1 ##############################################################################
2 # Copyright (c) 2017 Tim Rozet (trozet@redhat.com) and others.
3 #
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
9
10 import copy
11 import iptc
12 import logging
13 import os
14 import pprint
15 import subprocess
16
17 from apex.common import utils
18 from apex.virtual import configure_vm as vm_lib
19 from virtualbmc import manager as vbmc_lib
20
21 DEFAULT_RAM = 8192
22 DEFAULT_PM_PORT = 6230
23 DEFAULT_USER = 'admin'
24 DEFAULT_PASS = 'password'
25 DEFAULT_VIRT_IP = '192.168.122.1'
26
27
28 def generate_inventory(target_file, ha_enabled=False, num_computes=1,
29                        controller_ram=DEFAULT_RAM, arch='x86_64',
30                        compute_ram=DEFAULT_RAM, vcpus=4):
31     """
32     Generates inventory file for virtual deployments
33     :param target_file:
34     :param ha_enabled:
35     :param num_computes:
36     :param controller_ram:
37     :param arch:
38     :param compute_ram:
39     :param vcpus:
40     :return:
41     """
42
43     node = {'mac_address': '',
44             'ipmi_ip': DEFAULT_VIRT_IP,
45             'ipmi_user': DEFAULT_USER,
46             'ipmi_pass': DEFAULT_PASS,
47             'pm_type': 'pxe_ipmitool',
48             'pm_port': '',
49             'cpu': vcpus,
50             'memory': DEFAULT_RAM,
51             'disk': 41,
52             'arch': arch,
53             'capabilities': ''
54             }
55
56     inv_output = {'nodes': {}}
57     if ha_enabled:
58         num_ctrlrs = 3
59     else:
60         num_ctrlrs = 1
61
62     for idx in range(num_ctrlrs + num_computes):
63         tmp_node = copy.deepcopy(node)
64         tmp_node['mac_address'] = vm_lib.generate_baremetal_macs(1)[0]
65         tmp_node['pm_port'] = DEFAULT_PM_PORT + idx
66         if idx < num_ctrlrs:
67             tmp_node['capabilities'] = 'profile:control'
68             tmp_node['memory'] = controller_ram
69         else:
70             tmp_node['capabilities'] = 'profile:compute'
71             tmp_node['memory'] = compute_ram
72         inv_output['nodes']['node{}'.format(idx)] = copy.deepcopy(tmp_node)
73
74     utils.dump_yaml(inv_output, target_file)
75
76     logging.info('Virtual environment file created: {}'.format(target_file))
77
78
79 def host_setup(node):
80     """
81     Handles configuring vmbc and firewalld/iptables
82     :param node: dictionary of domain names and ports for ipmi
83     :return:
84     """
85     vbmc_manager = vbmc_lib.VirtualBMCManager()
86     for name, port in node.items():
87         vbmc_manager.add(username=DEFAULT_USER, password=DEFAULT_PASS,
88                          port=port, address=DEFAULT_VIRT_IP, domain_name=name,
89                          libvirt_uri='qemu:///system',
90                          libvirt_sasl_password=False,
91                          libvirt_sasl_username=False)
92
93         # TODO(trozet): add support for firewalld
94         subprocess.call(['systemctl', 'stop', 'firewalld'])
95
96         # iptables rule
97         rule = iptc.Rule()
98         rule.protocol = 'udp'
99         match = rule.create_match('udp')
100         match.dport = str(port)
101         rule.add_match(match)
102         rule.target = iptc.Target(rule, "ACCEPT")
103         chain = iptc.Chain(iptc.Table(iptc.Table.FILTER), "INPUT")
104         chain.insert_rule(rule)
105         try:
106             subprocess.check_call(['vbmc', 'start', name])
107             logging.debug("Started vbmc for domain {}".format(name))
108         except subprocess.CalledProcessError:
109             logging.error("Failed to start vbmc for {}".format(name))
110             raise
111     logging.debug('vmbcs setup: {}'.format(vbmc_manager.list()))
112
113
114 def virt_customize(ops, target):
115     """
116     Helper function to virt customize disks
117     :param ops: list of of operations and arguments
118     :param target: target disk to modify
119     :return: None
120     """
121     logging.info("Virt customizing target disk: {}".format(target))
122     virt_cmd = ['virt-customize']
123     for op in ops:
124         for op_cmd, op_arg in op.items():
125             virt_cmd.append(op_cmd)
126             virt_cmd.append(op_arg)
127     virt_cmd.append('-a')
128     virt_cmd.append(target)
129     if not os.path.isfile(target):
130         raise FileNotFoundError
131     my_env = os.environ.copy()
132     my_env['LIBGUESTFS_BACKEND'] = 'direct'
133     logging.debug("Virt-customizing with: \n{}".format(virt_cmd))
134     try:
135         logging.debug(subprocess.check_output(virt_cmd, env=my_env,
136                                               stderr=subprocess.STDOUT))
137     except subprocess.CalledProcessError as e:
138         logging.error("Error executing virt-customize: {}".format(
139                       pprint.pformat(e.output)))
140         raise