def install_node_exporter(state, host): if not host.data.node_exporter_version: raise DeployError( 'No node_exporter_version set for this host, refusing to install node_exporter!', ) server.user( state, host, {'Create the node_exporter user (Called prometheus by default)'}, '{{ host.data.node_exporter_user }}', shell='/sbin/nologin', ) files.directory( state, host, {'Ensure the node_exporter install directory exists'}, '{{ host.data.node_exporter_install_dir }}', user=host.data.node_exporter_user, group=host.data.node_exporter_user, ) # Work out the filename host.data.node_exporter_version_name = ( 'node_exporter-{0}.linux-' 'amd64' if host.fact.arch == 'x86_64' else host.fact.arch).format( host.data.node_exporter_version) host.data.node_exporter_temp_filename = state.get_temp_filename( 'node_exporter-{0}'.format(host.data.node_exporter_version), ) download_node_exporter = files.download( state, host, {'Download node_exporter'}, ('{{ host.data.node_exporter_download_base_url }}/' 'v{{ host.data.node_exporter_version }}/' '{{ host.data.node_exporter_version_name }}.tar.gz'), '{{ host.data.node_exporter_temp_filename }}', ) # If we downloaded node_exporter, extract it! if download_node_exporter.changed: server.shell( state, host, {'Extract node_exporter'}, 'tar -xzf {{ host.data.node_exporter_temp_filename }}' ' -C {{ host.data.node_exporter_install_dir }}', ) files.link( state, host, {'Symlink node_exporter to /usr/bin'}, '{{ host.data.node_exporter_bin_dir }}/node_exporter', # link '{{ host.data.node_exporter_install_dir }}/' '{{ host.data.node_exporter_version_name }}/node_exporter', )
def install_controller_services(state, host): apt.packages( state, host, {'Install packages'}, [ 'apache2', 'mariadb-server', 'rabbitmq-server', 'memcached', 'python-memcache', 'python-pymysql', ], ) # MariaDB mariadb_configure = files.template( state, host, {'Generate MariaDB config'}, get_template_path('mysql.cnf.j2'), '/etc/mysql/mariadb.conf.d/99-openstack.cnf', ) init.service( state, host, {'Restart MariadB'}, 'mysql', restarted=mariadb_configure.changed, ) # RabbitMQ server.shell( state, host, {'Setup RabbitMQ user'}, ( 'rabbitmqctl add_user openstack {{ host.data.rabbitmq_password }} || true', 'rabbitmqctl set_permissions openstack ".*" ".*" ".*"', ), ) # Memcached memcached_configure = files.template( state, host, {'Generate memcached config'}, get_template_path('memcached.conf.j2'), '/etc/memcached.conf', ) init.service( state, host, {'Restart memcached'}, 'memcached', restarted=memcached_configure.changed, )
def install_glance_service(state, host): install_glance = apt.packages( state, host, {'Install glance'}, ['glance'], ) if install_glance.changed: create_database(state, host, 'glance') create_service_user(state, host, 'glance', 'image') create_service_endpoints(state, host, 'image', ':9292') generate_glance_api_config = files.template( state, host, {'Generate glance-api config'}, get_template_path('glance-api.conf.j2'), '/etc/glance/glance-api.conf', ) generate_glance_registry_config = files.template( state, host, {'Generate glance-registry config'}, get_template_path('glance-registry.conf.j2'), '/etc/glance/glance-registry.conf', ) server.shell( state, host, {'Sync the glance database'}, 'glance-manage db_sync', ) should_restart_glance = (generate_glance_api_config.changed or generate_glance_registry_config.changed) init.service( state, host, {'Restart glance-registry'}, 'glance-registry', restarted=should_restart_glance, ) init.service( state, host, {'Restart glance-api'}, 'glance-api', restarted=should_restart_glance, )
def install_neutron_service(state, host, nova=False, placement=False): create_database(state, host, 'neutron') neutron_install = apt.packages( state, host, {'Install neutron network controller packages'}, [ 'neutron-server', 'neutron-plugin-ml2', ], ) if neutron_install.changed: create_service_user(state, host, 'neutron', 'network') create_service_endpoints(state, host, 'network', ':9696') neutron_configure = files.template( state, host, {'Generate neutron config'}, get_template_path('neutron-controller.conf.j2'), '/etc/neutron/neutron.conf', nova=nova, ) ml2_plugin_configure = files.template( state, host, {'Generate neutron ml2 plugin config'}, get_template_path('ml2_conf.ini.j2'), '/etc/neutron/plugins/ml2/ml2_conf.ini', ) server.shell( {'Sync the neutron database'}, ''' neutron-db-manage --config-file /etc/neutron/neutron.conf \ --config-file /etc/neutron/plugins/ml2/ml2_conf.ini \ upgrade head ''', ) init.service( state, host, {'Restart neutron-server'}, 'neutron-server', restarted=neutron_configure.changed or ml2_plugin_configure.changed, )
def create_service_endpoints(state, host, name, port): server.shell( state, host, {'Create {0} service endpoints'.format(name)}, ( 'openstack endpoint create --region RegionOne %s public http://{{ host.data.controller_host }}%s' % (name, port), # noqa 'openstack endpoint create --region RegionOne %s internal http://{{ host.data.controller_host }}%s' % (name, port), # noqa 'openstack endpoint create --region RegionOne %s admin http://{{ host.data.controller_host }}%s' % (name, port), # noqa ), env=make_admin_env(host), )
def create_service_user(state, host, name, type_): password = '******' % name server.shell( state, host, {'Create {0} {1} user/service'.format(name, type_)}, ( 'openstack user create --domain default --password {0} {1}'.format( password, name), 'openstack role add --project service --user {0} admin'.format( name), 'openstack service create --name {0} {1}'.format(name, type_), ), env=make_admin_env(host), )
def brook(state: Optional[State] = None, host: Optional[Host] = None) -> None: """Install brook.""" if host.fact.arch == "x86_64": files.download( source_url= "https://github.com/txthinking/brook/releases/download/v20200909/brook_linux_amd64", # noqa: E950 destination="/usr/local/bin/brook", mode=755, sha256sum= "efc4dc925bcaff4d33450fbcd02351da8f971f5cea6b84501a3d2a6f94876adf", # noqa: E950 state=state, host=host, ) server.shell( f"nohup brook server -l {_get_host_ip(host.name)}:{environ['BROOK_PORT']} -p {environ['BROOK_PASSWORD']} > /dev/null 2> /dev/null &", # noqa: B950 success_exit_codes=[0, 1], state=state, host=host, ) else: python.raise_exception(state, host, NotImplementedError)
def wireguard(state: Optional[State] = None, host: Optional[Host] = None) -> None: """Install wireguard.""" if host.fact.os == "Linux": if host.fact.linux_distribution["release_meta"]["ID"] in [ "debian", "ubuntu" ]: apt.packages(packages=["wireguard"], state=state, host=host) else: python.raise_exception(exception_class=NotImplementedError, state=state, host=host) else: python.raise_exception(exception_class=NotImplementedError, state=state, host=host) files.template( template_filename="templates/wg0.conf.j2", remote_filename="/etc/wireguard/wg0.conf", create_remote_dir=True, state=state, host=host, wg_private_key=environ["WG_PRIVATE_KEY"], wg_port=environ["WG_PORT"], wg_interface=environ["WG_INTERFACE"], wg_peer_1_public_key=environ["WG_PEER_1_PUBLIC_KEY"], wg_peer_2_public_key=environ["WG_PEER_2_PUBLIC_KEY"], ) server.sysctl(key="net.ipv4.ip_forward", value=1, state=state, host=host) server.sysctl(key="net.ipv6.conf.all.forwarding", value=1, state=state, host=host) server.shell(commands=["wg-quick up wg0"], success_exit_codes=[0, 1], state=state, host=host)
def ipv6(state: Optional[State] = None, host: Optional[Host] = None) -> None: """Test if ipv6 configured correctly.""" server.shell(commands=["ping6 -c1 ::1"], state=state, host=host)
'/home/vagrant/example_files', user='******', group='pyinfra', delete=True, sudo=True, ) # Generate files from local jinja2 templates files.template( 'templates/template.txt.j2', '/home/vagrant/template.txt', ) # Execute arbitrary shell commands server.shell([ 'echo "Shell command"', 'echo "My hostname is {{ host.fact.hostname }}"', ]) # and scripts server.script( 'files/test.sh', ) # Manage init systems init.service( 'cron', running=True, sudo=True, ignore_errors=True, on_error=on_pyinfra_error, )
format(code_name), ) # install kernel headers # Note: host.fact.os_version is the same as `uname -r` (ex: '4.15.0-72-generic') apt.packages( { 'Install VirtualBox version {} and ' 'kernel headers for {}'.format(virtualbox_version, host.fact.os_version), }, [ 'virtualbox-{}'.format(virtualbox_version), 'linux-headers-{}'.format(host.fact.os_version), ], update=True, ) server.shell( { 'Run vboxconfig which will stop/start VirtualBox services and build kernel modules' }, '/sbin/vboxconfig', ) python.call( {'Verify VirtualBox version'}, verify_virtualbox_version, version=virtualbox_version, )
from pyinfra.modules import server SUDO = True # Various different outputs # To see output need to run pyinfra with '-v' a = server.script( {'Hello'}, 'files/hello.bash', ) print('a', a) # To see output need to run pyinfra with '-v' b = server.shell( {'Say Hello'}, 'echo Hello', ) print('b', b)
from pyinfra import host, local, state from pyinfra.modules import files, server server.shell( {'First main operation'}, 'echo first_main_op', ) # Create some conditional branches if host.name == 'somehost': server.shell( {'Second main operation'}, 'echo second_main_op', ) elif host.name == 'anotherhost': local.include('tasks/a_task.py') # Include the whole file again, but for all hosts local.include('tasks/a_task.py') # Do a loop which will generate duplicate op hashes for i in range(2): server.shell( {'Loop-{0} main operation'.format(i)}, 'echo loop_{0}_main_operation'.format(i), ) files.file( {'Third main operation'}, 'files/a_file', '/a_file',
def install_keystone_service(state, host): create_database(state, host, 'keystone') keystone_install = apt.packages( state, host, {'Install keystone'}, ['keystone'], ) files.template( state, host, {'Generate keystone config'}, get_template_path('keystone.conf.j2'), '/etc/keystone/keystone.conf', ) server.shell( state, host, {'Sync the keystone database'}, 'keystone-manage db_sync', ) # Bootstrap keystone: only do this if newly installed if keystone_install.changed: server.shell( state, host, ''' keystone-manage fernet_setup --keystone-user keystone --keystone-group keystone keystone-manage credential_setup --keystone-user keystone --keystone-group keystone keystone-manage bootstrap \ --bootstrap-password {{ host.data.admin_password }} \ --bootstrap-admin-url http://{{ host.data.controller_host }}:35357/v3/ \ --bootstrap-internal-url http://{{ host.data.controller_host }}:35357/v3/ \ --bootstrap-public-url http://{{ host.data.controller_host }}:5000/v3/ \ --bootstrap-region-id RegionOne ''') update_apache_config = files.line( state, host, {'Set ServerName in apache2 config'}, '/etc/apache2/apache2.conf', 'ServerName.*', replace='ServerName {{ host.data.ssh_hostname }}', ) init.service( state, host, {'Restart apache2'}, 'apache2', restarted=update_apache_config.changed, ) if keystone_install.changed: server.shell( state, host, {'Create initial projects/users/roles'}, ( 'openstack project create --domain default service', 'openstack project create --domain default user', 'openstack user create --domain default --password hamble user-1', 'openstack role create user', 'openstack role add --project user --user user-1 user', ), env=make_admin_env(host), )
files.directory( {'Ensure the `{}` exists'.format(tftp_dir)}, tftp_dir, ) tar_file = 'netboot.tar.gz' tar_file_full_path = '/tmp/{}'.format(tar_file) files.download( {'Download `{}`'.format(tar_file)}, 'http://archive.ubuntu.com/ubuntu/dists/bionic-updates/main/' 'installer-amd64/current/images/netboot/{}'.format(tar_file), tar_file_full_path, ) server.shell( {'Extract files from tar file'}, 'tar -xvzf {} -C {}'.format(tar_file_full_path, tftp_dir), ) server.shell( {'Change permissions'}, 'chown -R nobody:nogroup {}'.format(tftp_dir), ) uefi_file = 'grubnetx64.efi.signed' uefi_full_path = '{}/{}'.format(tftp_dir, uefi_file) files.download( {'Download `{}`'.format(uefi_file)}, 'http://archive.ubuntu.com/ubuntu/dists/trusty/main/' 'uefi/grub2-amd64/current/grubnetx64.efi.signed', uefi_full_path, )
# Copy local files to remote host files.put('files/file.txt', '/home/vagrant/file.txt', mode=777) # and sync directories files.sync('files', '/home/vagrant/example_files', user='******', group='pyinfra', delete=True, sudo=True) # Generate files from local jinja2 templates files.template('templates/template.txt.j2', '/home/vagrant/template.txt') # Execute arbitrary shell commands server.shell( ['echo "Shell command"', 'echo "My hostname is {{ host.fact.hostname }}"']) # and scripts server.script('files/test.sh') # Manage init systems init.d('crond', running=True, sudo=True, ignore_errors=True) # Include roles local.include( 'roles/bsd_role.py', hosts=inventory.bsd # optionally limit the role to a subset of hosts ) # Storing this fact to avoid typing it so much (because the example targets a whole bunch # of distros [& 2 OSs]). distro = host.fact.linux_distribution
from pyinfra.modules import server server.shell( {'First task operation'}, 'echo first_task_operation', ) server.shell( {'Second task operation'}, 'echo second_task_operation', )
def install_etcd(state, host): if not host.data.etcd_version: raise DeployError( 'No etcd_version set for this host, refusing to install etcd!', ) server.user( state, host, {'Create the etcd user'}, 'etcd', shell='/sbin/nologin', ) files.directory( state, host, {'Ensure the etcd data directory exists'}, '{{ host.data.etcd_data_dir }}', user=host.data.etcd_user, group=host.data.etcd_user, ) files.directory( state, host, {'Ensure the etcd install directory exists'}, host.data.etcd_install_dir, user=host.data.etcd_user, group=host.data.etcd_user, ) # Work out the filename host.data.etcd_version_name = ('etcd-{0}-linux-' 'amd64' if host.fact.arch == 'x86_64' else host.fact.arch).format( host.data.etcd_version) host.data.etcd_temp_filename = state.get_temp_filename( 'etcd-{0}'.format(host.data.etcd_version), ) download_etcd = files.download( state, host, {'Download etcd'}, ('{{ host.data.etcd_download_base_url }}/' '{{ host.data.etcd_version }}/' '{{ host.data.etcd_version_name }}.tar.gz'), '{{ host.data.etcd_temp_filename }}', ) # If we downloaded etcd, extract it! server.shell( state, host, {'Extract etcd'}, 'tar -xzf {{ host.data.etcd_temp_filename }} -C {{ host.data.etcd_install_dir }}', when=download_etcd.changed, ) files.link( state, host, {'Symlink etcd to /usr/bin'}, '{{ host.data.etcd_bin_dir }}/etcd', # link '{{ host.data.etcd_install_dir }}/{{ host.data.etcd_version_name }}/etcd', ) files.link( state, host, {'Symlink etcdctl to {0}'.format(host.data.etcd_bin_dir)}, '{{ host.data.etcd_bin_dir }}/etcdctl', '{{ host.data.etcd_install_dir }}/{{ host.data.etcd_version_name }}/etcdctl', )
from pyinfra.modules import files, server CONNECT_TIMEOUT = 1 FAIL_PERCENT = 0 server.user( {'Add pyinfra user'}, 'pyinfra', home='/home/pyinfra', shell='/bin/bash', ) files.file( {'Add log file'}, '/var/log/pyinfra.log', user='******', mode=777, ) files.put( {'Copy a file'}, '../files/test_file.txt', '/home/pyinfra/test_file.txt', user='******', ) server.shell( {'Run some shell'}, 'echo "hi!"', )