def setup(self): """ easy_install, pipをインストールします。 また、pipはパッケージインストール時にソースからコンパイルするため、 いくつかのdevelパッケージをインストールしておきます。 """ self.init() git.setup() self.install_packages() with api.warn_only(): result = run('which easy_install') if result.return_code != 0: sudo('sh -c "cd /tmp/ && wget https://bootstrap.pypa.io/ez_setup.py -O - | python"') with api.warn_only(): result = run('which pip') if result.return_code != 0: sudo('easy_install pip') if self.prefix != '/usr': sudo('pip install virtualenv') if not filer.exists(self.prefix): sudo('virtualenv {0} --system-site-packages'.format(self.prefix))
def setup_pcs(self): data = self.init() if env.host == data['hosts'][0]: if not filer.exists('/etc/corosync/authkey'): sudo('corosync-keygen -l') sudo('cp /etc/corosync/authkey /tmp/authkey') sudo('chmod 666 /tmp/authkey') api.get('/tmp/authkey', '/tmp/authkey') sudo('rm /tmp/authkey') else: if not filer.exists('/etc/corosync/authkey'): api.put('/tmp/authkey', '/tmp/authkey') sudo('mv /tmp/authkey /etc/corosync/authkey') sudo('chown root:root /etc/corosync/authkey') sudo('chmod 400 /etc/corosync/authkey') data['bindnetaddr'] = env['node']['ip']['default_dev']['subnet'].split( '/')[0] nodes = [] for i, host in enumerate(env.hosts): ip = socket.gethostbyname(host) nodes.append({'id': i, 'ip': ip}) data['nodes'] = nodes if filer.template('/etc/corosync/corosync.conf', data=data): sudo('systemctl restart pacemaker') sudo('systemctl restart corosync') with api.warn_only(): result = sudo("pcs cluster status") if result.return_code != 0: sudo("pcs cluster start")
def run_remote(): remote = env.remote_map[env.host] root, dirname = CONF._repo_dir.rsplit('/', 1) storage_dir = os.path.join(dirname, CONF._storage_dir.rsplit('/', 1)[1]) repo_tar = '{0}/fabrepo.tar.gz'.format(CONF._tmp_dir) remote_repo = '{0}/fabrepo'.format(CONF._remote_tmp_dir) remote_repo_tar = '{0}/fabrepo.tar.gz'.format(CONF._remote_tmp_dir) local('cd {0} && tar -zcf {1} {2} --exclude .git --exclude {3}'.format( root, repo_tar, dirname, storage_dir)) scp(repo_tar, remote_repo_tar) run('rm -rf $HOME/fabric-repo') run('cd {0} && tar -xf fabrepo.tar.gz -C $HOME'.format(CONF._remote_tmp_dir, remote_repo)) task_name = '' if env.is_setup: task_name = 'setup' elif env.is_check: task_name = 'check' elif env.is_manage: task_name = 'manage:{0}'.format(','.join(env.func_names)) cluster_map = {} with api.shell_env(password=env.password): for cluster in remote['clusters']: run('cd $HOME/{0} && fab node:{1}/{2},yes {3} -u $USER -p $password'.format( dirname, cluster, remote['host_pattern'], task_name, env.password)) with api.warn_only(): yaml_str = run('cat $HOME/{0}/nodes/{1}/__cluster.yml'.format(dirname, cluster)) cluster_map[cluster] = yaml.load(yaml_str) return cluster_map
def install(self, option=''): with api.warn_only(): if env.node['package_manager'] == 'yum': self.result = run('rpm -q {0}'.format(self.package_name)) if not self.result.return_code == 0: if self.path: self.result = sudo('yum install {0} -y {1}'.format(self.path, option)) else: self.result = sudo('yum install {0} -y {1}'.format( self.package_name, option)) elif env.node['package_manager'] == 'apt': self.result = run('dpkg -l {0} | grep "^ii "'.format(self.package_name)) if not self.result.return_code == 0: if self.path: self.result = sudo('apt-get install {0} -y {1}'.format(self.path, option)) else: self.result = sudo('apt-get install {0} -y {1}'.format( self.package_name, option)) else: self.unsupport() print self.result if self.result.return_code != 0: msg = 'Failed install {0}.'.format(self.package_name) log.error(msg) raise Exception(msg) return self
def exists(dest, is_local=False): cmd_exists = '[ -e {0} ]'.format(dest) if is_local or env.is_local: result, result_out = cmd(cmd_exists) return True if result == 0 else False else: with api.warn_only(): return True if sudo(cmd_exists).return_code == 0 else False
def add(name, group=None): with api.warn_only(): passwd = run('cat /etc/passwd | grep ^{0}:'.format(name)) if passwd.return_code != 0: sudo('useradd {0} -M -s/bin/false'.format(name)) if group is not None: sudo('gpasswd -add {0} {1}'.format(name, group))
def add(name, gid=None): with api.warn_only(): getent = sudo('getent group | grep ^{0}:'.format(name)) if getent.return_code != 0: if gid is None: sudo('groupadd {0}'.format(name)) else: sudo('groupadd -g {0} {1}'.format(gid, name))
def create_flavor(self, name, ram, disk, vcpu): with api.warn_only(): result = self.cmd("flavor-list 2>/dev/null | grep ' {0} '".format(name)) if result.return_code == 0: return else: self.cmd("flavor-create --is-public true {0} auto {1} {2} {3}".format( name, ram, disk, vcpu))
def create(self): data = self.data sudo('modprobe kvm') sudo('modprobe kvm_intel') for i, vm in enumerate(data['libvirt_vms']): instance_dir = os.path.join(self.instances_dir, vm['name']) filer.mkdir(instance_dir) image_path = '{0}/vm.img'.format(instance_dir) vm['image_path'] = image_path src_image_path = self.wget_src_image(vm) if not filer.exists(image_path): sudo('cp {0} {1}'.format(src_image_path, image_path)) sudo('qemu-img resize {0} {1}G'.format(image_path, vm.get('disk_size', 10))) configiso_path = self.create_configiso(vm, instance_dir) vm['configiso_path'] = configiso_path vm['mac'] = self.get_random_mac() domain_xml = self.create_domain_xml(vm, instance_dir) sudo("sed -i 's/^Defaults.*requiretty/# Defaults requiretty/' /etc/sudoers") sudo("virsh net-update default add ip-dhcp-host " "\"<host mac='{0}' name='{1}' ip='{2}' />\"".format( vm['mac'], vm['name'], vm['ip'])) sudo('virsh define {0}'.format(domain_xml)) sudo('chown -R root:root {0}'.format(instance_dir)) sudo('virsh start {0}'.format(vm['name'])) for vm in data['libvirt_vms']: while True: with api.warn_only(): if run('nmap -p 22 {0} | grep open'.format(vm['ip'])): break time.sleep(5) sudo("iptables -R FORWARD 1 -o virbr0 -s 0.0.0.0/0" " -d 192.168.122.0/255.255.255.0 -j ACCEPT") for vm in data['libvirt_vms']: for port in vm.get('ports', []): sudo("iptables -t nat -A PREROUTING -p tcp" " --dport {0[1]} -j DNAT --to {1}:{0[0]}".format( port, vm['ip'])) for ip in data['iptables']: for port in ip.get('ports', []): sudo("iptables -t nat -A PREROUTING -p tcp" " --dport {0[1]} -j DNAT --to {1}:{0[0]}".format( port, ip['ip'])) time.sleep(5)
def delete(self): data = self.data for i, vm in enumerate(data['libvirt_vms']): with api.warn_only(): sudo("virsh net-update default delete ip-dhcp-host \"`virsh net-dumpxml default" " | grep '{0}' | sed -e 's/^ *//'`\"".format(vm['ip'])) sudo('virsh list | grep {0} && virsh destroy {0}'.format(vm['name'])) sudo('virsh list --all | grep {0} && virsh undefine {0}'.format(vm['name'])) instance_dir = os.path.join(self.instances_dir, vm['name']) sudo('rm -rf {0}'.format(instance_dir))
def wrap_cmd(self, option, **kwargs): with api.warn_only(): service_manager = env.node['service_manager'] if service_manager == 'systemd': self.result = sudo('systemctl {0} {1}'.format(option, self.name), **kwargs) elif service_manager == 'service': self.result = sudo('/etc/init.d/{1} {0}'.format(option, self.name), **kwargs) elif service_manager == 'upstart': self.result = sudo('initctl {0} {1}'.format(option, self.name), **kwargs) else: self.unsupport() return self
def create_routers(self): data = self.init() with api.warn_only(): for router in data.get('routers', []): result = self.cmd('router-show {0}'.format(router['name'])) if result.return_code == 0: continue self.cmd('router-create {0}'.format(router['name'])) self.cmd('router-gateway-set {0} {1}'.format(router['name'], router['gateway'])) for interface in router['interfaces']: self.cmd('router-interface-add {0} {1}'.format(router['name'], interface))
def disable(self, **kwargs): with api.warn_only(): init_manager = env.node['init_manager'] if init_manager == 'systemd': self.result = sudo('systemctl disable {0}'.format(self.name), **kwargs) elif init_manager == 'chkconfig': self.result = sudo('chkconfig {0} off'.format(self.name), **kwargs) elif init_manager == 'update-rc.d': self.result = sudo('update-rc.d -f {0} remove'.format(self.name), **kwargs) else: self.unsupport() return self
def setup_pcs(self): data = self.init() if env.host == data['hosts'][0]: with api.warn_only(): result = sudo("pcs cluster status") if result.return_code != 0: ha_hosts = ' '.join(data['hosts']) sudo("pcs cluster auth {0} -u hacluster -p {1}".format( ha_hosts, data['ha_password'])) # pcs cluster setup で/etc/corosync/corosync.conf が自動生成される sudo("pcs cluster setup --name hacluster {0}".format(ha_hosts)) sudo("pcs cluster start --all") sudo("corosync-cfgtool -s")
def wrap_cmd(self, option, **kwargs): with api.warn_only(): service_manager = env.node['service_manager'] if service_manager == 'systemd': self.result = sudo( 'systemctl {0} {1}'.format(option, self.name), **kwargs) elif service_manager == 'service': self.result = sudo( '/etc/init.d/{1} {0}'.format(option, self.name), **kwargs) elif service_manager == 'upstart': self.result = sudo('initctl {0} {1}'.format(option, self.name), **kwargs) else: self.unsupport() return self
def upgrade(self): with api.warn_only(): if env.node['package_manager'] == 'yum': self.result = sudo('yum upgrade {0} -y'.format(self.package_name)) elif env.node['package_manager'] == 'apt': self.result = sudo('apt-get upgrade {0} -y'.format(self.package_name)) else: self.unsupport() if self.result.return_code != 0: msg = 'Failed upgrade {0}.'.format(self.package_name) log.error(msg) raise Exception(msg) return self
def setup_cluster(self): if self.is_tag('data'): data = self.init() if env.host == data['hosts'][0]: for vhost in data['vhost_map'].values(): sudo('rabbitmqctl set_policy all \'^.*\' \'{{"ha-mode": "all"}}\' -p {0}'.format(vhost)) # noqa else: with api.warn_only(): result = sudo('rabbitmqctl cluster_status | grep rabbit@rabbit0') if result.return_code != 0: sudo('rabbitmqctl stop_app') sudo('rabbitmqctl reset') sudo('rabbitmqctl join_cluster rabbit@rabbit0') sudo('rabbitmqctl start_app')
def disable(self, **kwargs): with api.warn_only(): init_manager = env.node['init_manager'] if init_manager == 'systemd': self.result = sudo('systemctl disable {0}'.format(self.name), **kwargs) elif init_manager == 'chkconfig': self.result = sudo('chkconfig {0} off'.format(self.name), **kwargs) elif init_manager == 'update-rc.d': self.result = sudo( 'update-rc.d -f {0} remove'.format(self.name), **kwargs) else: self.unsupport() return self
def delete(self): data = self.data for i, vm in enumerate(data['libvirt_vms']): with api.warn_only(): self.pdns.delete_record('{0}.{1}'.format(vm['name'], CONF.network.domain)) for port in vm['ports']: if port['ip'] == 'none': continue if sudo('virsh list | grep {0}'.format(vm['name'])).return_code == 0: sudo('virsh destroy {0}'.format(vm['name'])) if sudo('virsh list --all | grep {0}'.format(vm['name'])).return_code == 0: sudo('virsh undefine {0}'.format(vm['name'])) instance_dir = os.path.join(self.instances_dir, vm['name']) sudo('rm -rf {0}'.format(instance_dir))
def setup(): Package('python-crypto').uninstall() Package('python-devel').install() Package('libevent-devel').install() Package('libxml2-devel').install() Package('libxslt-devel').install() with api.warn_only(): if run('which easy_install').return_code != 0: sudo('wget https://bootstrap.pypa.io/ez_setup.py -O - | python') if run('which pip').return_code != 0: sudo('easy_install pip') sudo('pip install fabric==1.10.1') sudo('pip install pyyaml==3.11') sudo('pip install jinja2==2.7.3') sudo('pip install Django==1.6.5')
def set_os(): with api.warn_only(): result = run('cat /etc/os-release') if result.return_code == 0: # CentOS(Test: Ubuntu 14.10, Centos Linux 7 (Core)) re_search = re.search('PRETTY_NAME="(.+)"', result) os = re_search.group(1) env.node['os'] = os if re_ubuntu16.match(os): env.node['package_manager'] = 'apt' env.node['service_manager'] = 'systemd' env.node['init_manager'] = 'systemd' elif re_ubuntu.match(os): env.node['package_manager'] = 'apt' env.node['service_manager'] = 'service' env.node['init_manager'] = 'update-rc.d' elif re_centos.match(os): env.node['package_manager'] = 'yum' env.node['service_manager'] = 'systemd' env.node['init_manager'] = 'systemd' env.path += ':/sbin' else: result = run('cat /etc/centos-release') if result.return_code == 0: # CentOS(Test: CentOS 6.5) re_search = re.search('release ([0-9.]+) ', result) os = 'CentOS {0}'.format(re_search.group(1)) env.node['os'] = os env.node['package_manager'] = 'yum' env.node['service_manager'] = 'service' env.node['init_manager'] = 'chkconfig' env.path += ':/sbin' else: if run('which yum').return_code == 0: env.node['package_manager'] = 'yum' env.node['service_manager'] = 'service' env.node['init_manager'] = 'chkconfig' env.path += ':/sbin' run('env') if 'os' in env.node: return True else: return False
def setup_cluster(self): if self.is_tag('data'): data = self.init() if env.host == data['hosts'][0]: for vhost in data['vhost_map'].values(): sudo( 'rabbitmqctl set_policy all \'^.*\' \'{{"ha-mode": "all"}}\' -p {0}' .format(vhost)) # noqa else: with api.warn_only(): result = sudo( 'rabbitmqctl cluster_status | grep rabbit@rabbit0') if result.return_code != 0: sudo('rabbitmqctl stop_app') sudo('rabbitmqctl reset') sudo('rabbitmqctl join_cluster rabbit@rabbit0') sudo('rabbitmqctl start_app')
def setup(self): data = self.init() if self.is_tag('conf'): if env.node['package_manager'] == 'yum': if filer.template('/etc/my.cnf.d/server.cnf', data=data): self.handlers['restart_mariadb'] = True elif env.node['package_manager'] == 'apt': pass if self.is_tag('service'): if self.data['hosts'][0] == env.host: with api.warn_only(): result = sudo('systemctl status mariadb') if result.return_code != 0: sudo('galera_new_cluster') else: self.exec_handlers() self.enable_services().start_services() else: self.enable_services().start_services() self.exec_handlers() if self.is_tag('data'): # init root_password if not filer.exists('/root/.my.cnf'): root_password = data['root_password'] if data['hosts'][0] == env.host: if self.is_ubuntu(): sudo('mysqladmin password {0} -uroot -ptmppass'.format( root_password)) else: sudo('mysqladmin password {0} -uroot'.format( root_password)) filer.template('/root/.my.cnf', data={'root_password': root_password}) if data['hosts'][0] == env.host: self.create_users() self.delete_default_users() self.create_databases()
def file(dest, mode='644', owner='root:root', src=None, src_file=None, src_str=None, override=False): if src_str is not None: src_file = __create_src_file(dest, src_str) is_updated = False with api.warn_only(): if exists(dest) and not override: log.info('file "{0}" exists'.format(dest)) else: if not src_file: src_file = __get_src_file(dest, src_dirname='files', src=src) if env.is_local: sudo('cp {0} {1}'.format(src_file, dest)) else: scp(src_file, dest) is_updated = True sudo('chmod -R {0} {1}'.format(mode, dest) + ' && chown -R {0} {1}'.format(owner, dest)) return is_updated
def set_ip(): with api.warn_only(): result = run('ip r') if result.return_code == 0: devs = re.findall( '([0-9./]+) +dev +([a-zA-Z0-9\-]+) +proto +kernel +scope +link +src +([0-9.]+)', result) default = re.findall( 'default +via +([0-9.]+) +dev +([a-zA-Z0-9\-]+)', result) dev = default[0][1].split(' ')[0] ips = { 'default': { 'ip': default[0][0], 'dev': dev, } } for dev in devs: ip_data = { 'subnet': dev[0], 'dev': dev[1], 'ip': dev[2], } ips[dev[0]] = ip_data ips[dev[1]] = ip_data ips[dev[0].split('.')[0]] = ip_data ips['default_dev'] = ips[ips['default']['dev']] env.node['ip'] = ips return True else: return False
def install(self, option=''): with api.warn_only(): if env.node['package_manager'] == 'yum': self.result = run('rpm -q {0}'.format(self.package_name)) if not self.result.return_code == 0: if self.path: self.result = sudo('yum install {0} -y {1}'.format(self.path, option)) else: self.result = sudo('yum install {0} -y {1}'.format( self.package_name, option)) elif env.node['package_manager'] == 'apt': splited_name = self.package_name.split('=') if len(splited_name) > 1: package_name = splited_name[0] version = splited_name[1] else: package_name = self.package_name version = '' self.result = run('dpkg -l {0} | grep "^ii *{1}"'.format(package_name, version)) if not self.result.return_code == 0: if self.path: self.result = sudo('RUNLEVEL=1 apt-get install {0} -y {1}'.format( self.path, option)) else: self.result = sudo('RUNLEVEL=1 apt-get install {0} -y {1}'.format( self.package_name, option)) else: self.unsupport() if self.result.return_code != 0: msg = 'Failed install {0}.'.format(self.package_name) log.error(msg) raise Exception(msg) return self
def pip_show(self, package_name): """ pip show [package_name] の結果をパースして、タプル形式で返します。 """ with api.warn_only(): result = run('pip show {0}'.format(package_name)) if result == '': return None RE_NAME = re.compile('Name: (.+)\r') RE_VERSION = re.compile('Version: (.+)\r') finded_name = RE_NAME.findall(result) if len(finded_name) == 0: return None name = finded_name[0] finded_version = RE_VERSION.findall(result) if len(finded_version) == 0: return None version = finded_version[0] return (name, version)
def setup_network_bridge(self): data = self.init() if 'linuxbridge' in data['ml2']['mechanism_drivers']: sudo('modprobe bridge') elif 'openvswitch' in data['ml2']['mechanism_drivers']: sudo('modprobe -r bridge') Service('openvswitch').start().enable() sudo('ovs-vsctl br-exists {0} || ovs-vsctl add-br {0}'.format( data['ovs']['integration_bridge'])) filer.template( '/etc/sysconfig/network-scripts/ifcfg-{0}'.format( data['ovs']['integration_bridge']), src='network/ovs-ifcfg-br.j2', data=data) for mapping in data['ovs']['bridge_mappings']: pair = mapping.split(':') ovs_interface = pair[1] sudo('ovs-vsctl br-exists {0} || ovs-vsctl add-br {0}'.format(ovs_interface)) for mapping in data['ovs']['physical_interface_mappings']: pair = mapping.split(':') ovs_interface = pair[0] physical_interface = pair[1] backup_default_dev_file = '/etc/sysconfig/network-scripts/bk-ifcfg-defualt' if filer.exists(backup_default_dev_file): default = run('cat {0}'.format(backup_default_dev_file)) dev, ip, subnet, gateway = default.split(':') data['default_dev'] = { 'dev': dev, 'ip': ip, 'subnet': subnet, 'gateway': gateway, } else: sudo("echo '{0[dev]}:{0[ip]}:{0[subnet]}:{1}' > {2}".format( env.node['ip']['default_dev'], env.node['ip']['default']['ip'], backup_default_dev_file)) data['default_dev'] = env.node['ip']['default_dev'] data['default_dev']['gateway'] = env.node['ip']['default']['ip'] data['default_dev']['netmask'] = self.cidr( data['default_dev']['subnet'].split('/')[1]) if physical_interface == data['default_dev']['dev']: # create backup for default interface data['ovs_interface'] = ovs_interface filer.template( '/etc/sysconfig/network-scripts/ifcfg-{0}'.format(physical_interface), src='network/ovs-ifcfg-flat.j2', data=data) filer.template( '/etc/sysconfig/network-scripts/ifcfg-{0}'.format(ovs_interface), src='network/ovs-ifcfg-br-flat.j2', data=data) result = sudo('ovs-vsctl list-ports {0}'.format(ovs_interface)) if result.find(data['default_dev']['dev']) == -1: with api.warn_only(): api.reboot(180)
def template(dest, mode='644', owner='root:root', data={}, src=None, src_file=None, src_str=None, insert_eol_crlf=True): template_data = {} template_data.update(data) template_data['node'] = env.node template_data['cluster'] = env.cluster is_updated = False if src_str: src_file = __create_src_file(dest, src_str) if not src_file: src_file = __get_src_file(dest, src_dirname='templates', src=src) timestamp = int(time.time()) tmp_path = 'templates/{0}_{1}'.format(dest, timestamp) tmp_path = os.path.join(CONF._remote_storage_dir, tmp_path) # local_tmp_file = os.path.join(conf.TMP_DIR, env.host, tmp_path) local_tmp_file = CONF._tmp_dir + '/' + env.host + '/' + tmp_path local_tmp_dir = local_tmp_file.rsplit('/', 1)[0] mkdir(local_tmp_dir, is_local=True, use_sudo=False) template = j2_env.get_template(src_file) if not env.is_test: with open(local_tmp_file, 'w') as exf: exf.write(template.render(**template_data).encode('utf-8')) if insert_eol_crlf: exf.write('\n') if env.is_local: with api.warn_only(): if exists(dest): result = sudo('diff {0} {1}'.format(dest, local_tmp_file)) if result.return_code != 0: sudo('mv {0} {1}_old'.format(dest, local_tmp_file)) sudo('cp -f {0} {1}'.format(local_tmp_file, dest)) is_updated = True else: log.info('No change') else: sudo('diff /dev/null {1}'.format(dest, local_tmp_file)) sudo('cp -f {0} {1}'.format(local_tmp_file, dest)) is_updated = True else: tmp_dir = tmp_path.rsplit('/', 1)[0] mkdir(tmp_dir, mode='770', owner='{0}:root'.format(env.user)) scp(local_tmp_file, tmp_path) with api.warn_only(): if exists(dest): result = sudo('diff {0} {1}'.format(dest, tmp_path)) if result.return_code != 0: sudo('mv {0} {1}_old'.format(dest, tmp_path)) sudo('cp -f {0} {1}'.format(tmp_path, dest)) is_updated = True else: log.info('No change') else: sudo('diff /dev/null {1}'.format(dest, tmp_path)) sudo('cp -f {0} {1}'.format(tmp_path, dest)) is_updated = True sudo('sh -c "chmod {0} {1}'.format(mode, dest) + ' && chown {0} {1}"'.format(owner, dest)) return is_updated
def setup(self): data = self.init() node_os = env.node['os'] if re.match('Ubuntu 14.*', node_os): with api.warn_only(): sudo('apt-get update -y') self.install_packages() self.start_services() sudo('modprobe kvm') sudo('modprobe kvm_intel') for i, vm in enumerate(data['libvirt_vms']): template_data = { 'user': CONF.test.user, 'password': CONF.test.password, 'vm': vm, 'gateway': data['libvirt']['gateway'], 'netmask': data['libvirt']['netmask'], } vm_dir = '/var/lib/libvirt/images/{0}'.format(vm['name']) image_path = '{0}/vm.img'.format(vm_dir) metadata_path = '{0}/meta-data'.format(vm_dir) userdata_path = '{0}/user-data'.format(vm_dir) configiso_path = '{0}/config.iso'.format(vm_dir) src_image = vm['src_image'].rsplit('/', 1)[1] src_image_path = '/var/lib/libvirt/images/{0}'.format(src_image) src_image_format = 'qcow2' if src_image_path[-3:] == '.xz': src_image_path = src_image_path[:-3] src_image_format = 'xz' if not filer.exists(src_image_path): sudo('cd /var/lib/libvirt/images/ && wget {0}'.format(vm['src_image'])) if src_image_format == 'xz': sudo('cd /var/lib/libvirt/images/ && xz -d {0}'.format(src_image)) with api.warn_only(): sudo("virsh list --all | grep {0} && virsh destroy {0}" " && virsh undefine {0}".format(vm['name'])) sudo('rm -rf {0}'.format(vm_dir)) filer.mkdir(vm_dir) if not filer.exists(image_path): sudo('cp {0} {1}'.format(src_image_path, image_path)) sudo('qemu-img resize {0} {1}G'.format(image_path, vm.get('disk_size', 10))) filer.template(metadata_path, src='meta-data', data=template_data) filer.template(userdata_path, src=vm['template'], data=template_data) if not filer.exists(configiso_path): sudo('genisoimage -o {0} -V cidata -r -J {1} {2}'.format( configiso_path, metadata_path, userdata_path)) sudo("sed -i 's/^Defaults.*requiretty/# Defaults requiretty/' /etc/sudoers") vm['uuid'] = str(uuid.uuid1()) vm['image_path'] = image_path vm['configiso_path'] = configiso_path vm['tap'] = 'tap{0}'.format(i) vm['mac'] = self.get_random_mac() domain_xml = '/tmp/domain-{0}.xml'.format(vm['name']) filer.template(domain_xml, src='domain.xml', data=vm) with api.warn_only(): sudo("virsh net-update default delete ip-dhcp-host \"`virsh net-dumpxml default | grep '{0}' | sed -e 's/^ *//'`\"".format(vm['ip'])) sudo("virsh net-update default add ip-dhcp-host " "\"<host mac='{0}' name='{1}' ip='{2}' />\"".format( vm['mac'], vm['name'], vm['ip'])) sudo('virsh define {0}'.format(domain_xml)) sudo('virsh start {0}'.format(vm['name'])) # sudo("virt-install" # " --connect=qemu:///system" # " --name={name} --vcpus={vcpus} --ram={ram}" # " --accelerate --hvm --virt-type=kvm" # " --cpu host" # " --network bridge=virbr0,model=virtio" # " --disk {image_path},format=qcow2 --import" # " --disk {configiso_path},device=cdrom" # " --nographics &".format( # name=vm['name'], # vcpus=vm['vcpus'], # ram=vm['ram'], # image_path=image_path, # configiso_path=configiso_path, # ip=vm['ip'], # ), pty=False) # ), pty=False) for vm in data['libvirt_vms']: while True: with api.warn_only(): if run('nmap -p 22 {0} | grep open'.format(vm['ip'])): break time.sleep(5) sudo("iptables -R FORWARD 1 -o virbr0 -s 0.0.0.0/0" " -d 192.168.122.0/255.255.255.0 -j ACCEPT") for vm in data['libvirt_vms']: for port in vm.get('ports', []): sudo("iptables -t nat -A PREROUTING -p tcp" " --dport {0[1]} -j DNAT --to {1}:{0[0]}".format( port, vm['ip'])) for ip in data['iptables']: for port in ip.get('ports', []): sudo("iptables -t nat -A PREROUTING -p tcp" " --dport {0[1]} -j DNAT --to {1}:{0[0]}".format( port, ip['ip']))
def create(self): data = self.data sudo('modprobe kvm') sudo('modprobe kvm_intel') network = CONF.network.libvirt_net.split(':') bridge = network[0] brctl_show = sudo('brctl show') if brctl_show.find(bridge) == -1: sudo('brctl addbr {0}'.format(bridge)) ip_network = IPNetwork(network[1]) gateway_ip = '{0}/{1}'.format(ip_network.ip + 1, ip_network.prefixlen) dhcp_ip = '{0}/{1}'.format(ip_network.ip + 2, ip_network.prefixlen) bridge_info = sudo('ip addr show dev {0}'.format(bridge)) if bridge_info.find(gateway_ip) == -1: sudo('ip addr add {0} dev {1}'.format(gateway_ip, bridge)) if bridge_info.find('DOWN') != -1: sudo('ip link set {0} up'.format(bridge)) sudo('ip route add 10.0.0.0/8 via {0}'.format(ip_network.ip + 1)) network_seg = "{0}/{1}".format(ip_network.ip, ip_network.netmask) ip_netns = sudo('ip netns show') dhcp_netns = 'dhcp-{0}'.format(bridge) dhcp_veth_br = 'ns-{0}'.format(bridge) dhcp_veth = 'veth-{0}'.format(bridge) if ip_netns.find(dhcp_netns): sudo('ip netns add {0}'.format(dhcp_netns)) if brctl_show.find(dhcp_veth_br) == -1: sudo('ip link add {0} type veth peer name {1}'.format(dhcp_veth_br, dhcp_veth)) sudo('brctl addif {0} {1}'.format(bridge, dhcp_veth_br)) sudo('ip link set {0} up'.format(dhcp_veth_br)) sudo('ip link set {0} netns {1}'.format(dhcp_veth, dhcp_netns)) sudo('ip netns exec {0} ip addr add dev {1} {2}'.format(dhcp_netns, dhcp_veth, dhcp_ip)) sudo('ip netns exec {0} ip link set {1} up'.format(dhcp_netns, dhcp_veth)) # ss_ln = sudo('ip netns exec {0} ss -ln'.format(dhcp_netns)) # if ss_ln.find('*:67') == -1: # sudo('ip netns exec {0} dnsmasq -p 0 --dhcp-range 172.16.100.3,172.16.100.254,12h'.format( # noqa # dhcp_netns, ip_network[3], ip_network[-2])) ss_ln = sudo('ss -ln'.format(dhcp_netns)) if ss_ln.find('*:67') == -1: sudo('dnsmasq -p 0 --dhcp-range=172.16.100.3,172.16.100.254') for i, vm in enumerate(data['libvirt_vms']): instance_dir = os.path.join(self.instances_dir, vm['name']) filer.mkdir(instance_dir) vm['bridge'] = bridge vm['hostname'] = '{0}.{1}'.format(vm['name'], CONF.network.domain) image_path = '{0}/vm.img'.format(instance_dir) vm['image_path'] = image_path src_image_path = self.wget_src_image(vm) if not filer.exists(image_path): sudo('cp {0} {1}'.format(src_image_path, image_path)) sudo('qemu-img resize {0} {1}G'.format(image_path, vm.get('disk_size', 10))) if 'disk_cache' not in vm: vm['disk_cache'] = 'none' elif vm['disk_cache'] not in ['none', 'writethrough', 'writeback', 'directsync', 'unsafe', 'default']: raise Exception('Invalid disk_cache: {0}'.format(vm['disk_cache'])) configiso_path = self.create_configiso(vm, instance_dir) vm['configiso_path'] = configiso_path alias_index = 0 pci_slot_num = 2 for port in vm['ports']: mac = self.get_random_mac() port['mac'] = mac port['tap'] = 'tap{0}'.format(mac.replace(':', '')) port['pci_slot'] = '0x0{0}'.format(pci_slot_num) pci_slot_num += 1 port['alias_name'] = 'net{0}'.format(alias_index) alias_index += 1 vm['memballoon'] = { 'pci_slot': '0x0{0}'.format(pci_slot_num) } domain_xml = self.create_domain_xml(vm, instance_dir) sudo("sed -i 's/^Defaults.*requiretty/# Defaults requiretty/' /etc/sudoers") for port in vm['ports']: if port['ip'] == 'none': continue # sudo("virsh net-update {3} add ip-dhcp-host " # "\"<host mac='{0}' name='{1}' ip='{2}' />\"".format( # port['mac'], vm['name'], port['ip'], bridge)) sudo('virsh define {0}'.format(domain_xml)) sudo('chown -R root:root {0}'.format(instance_dir)) sudo('virsh start {0}'.format(vm['name'])) nat_table = sudo("iptables -t nat -L") if nat_table.find(network_seg) == -1: # sudo("iptables -R FORWARD 1 -o {0} -s {1}" # " -d 0.0.0.0/0 -j ACCEPT".format(bridge, network_seg)) sudo("iptables -t filter -A FORWARD -s 0.0.0.0/0 -d {0} -j ACCEPT".format(network_seg)) sudo("iptables -t filter -A FORWARD -d 0.0.0.0/0 -s {0} -j ACCEPT".format(network_seg)) nat_table = sudo("iptables -t nat -L") if nat_table.find(network_seg) == -1: sudo("iptables -t nat -A POSTROUTING -p TCP -s {0} ! -d {0} -j MASQUERADE --to-ports 1024-65535".format( network_seg)) sudo("iptables -t nat -A POSTROUTING -p UDP -s {0} ! -d {0} -j MASQUERADE --to-ports 1024-65535".format( network_seg)) sudo("iptables -t nat -A POSTROUTING -s {0} ! -d {0} -j MASQUERADE".format( network_seg)) sudo("iptables -t nat -A POSTROUTING -s {0} -d 255.255.255.255 -j RETURN".format( network_seg)) sudo("iptables -t nat -A POSTROUTING -s {0} -d base-address.mcast.net/24 -j RETURN".format( network_seg)) for vm in data['libvirt_vms']: self.pdns.create_record(vm['name'], CONF.network.domain, 'A', vm['ports'][0]['ip']) while True: with api.warn_only(): if run('nmap -p 22 {0} | grep open'.format(vm['ports'][0]['ip'])): break time.sleep(5) for ip in data.get('iptables', {}): for port in ip.get('ports', []): if ip['ip'] == 'none': continue sudo("iptables -t nat -A PREROUTING -p tcp" " --dport {0[1]} -j DNAT --to {1}:{0[0]}".format( port, ip['ip'])) time.sleep(60)