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