Commit 109d97c6 authored by dobli's avatar dobli
Browse files

split hostname from building name

parent a191a409
...@@ -137,51 +137,52 @@ def generate_initial_compose(): ...@@ -137,51 +137,52 @@ def generate_initial_compose():
yaml.dump(init_content, compose_f) yaml.dump(init_content, compose_f)
def add_sftp_service(hostname, number=0): def add_sftp_service(building, number=0):
"""Generates an sftp entry and adds it to the compose file """Generates an sftp entry and adds it to the compose file
:hostname: names of host that the services is added to :building: names of building that the services is added to
:number: increment of exposed port to prevent overlaps :number: increment of exposed port to prevent overlaps
""" """
# compose file # compose file
compose_path = f'{custom_path}/{COMPOSE_NAME}' compose_path = f'{custom_path}/{COMPOSE_NAME}'
# service name # service name
service_name = f'sftp_{hostname}' service_name = f'sftp_{building}'
# template # template
template = get_service_template(Service.SFTP.prefix) template = get_service_template(Service.SFTP.prefix)
# only label contraint is building # only label contraint is building
template['deploy']['placement']['constraints'][0] = ( template['deploy']['placement']['constraints'][0] = (
f"{CONSTRAINTS['building']} == {hostname}") f"{CONSTRAINTS['building']} == {building}")
template['ports'] = [f'{2222 + number}:22'] template['ports'] = [f'{2222 + number}:22']
# attach volumes # attach volumes
volume_base = '/home/ohadmin/' volume_base = '/home/ohadmin/'
template['volumes'] = get_attachable_volume_list(volume_base, hostname) template['volumes'] = get_attachable_volume_list(volume_base, building)
add_or_update_compose_service(compose_path, service_name, template) add_or_update_compose_service(compose_path, service_name, template)
def add_openhab_service(hostname): def add_openhab_service(building, host):
"""Generates an openhab entry and adds it to the compose file """Generates an openhab entry and adds it to the compose file
:hostname: names of host that the services is added to :building: name of building that the services is added to
:host: host the building is added to, used for routing
""" """
# compose file # compose file
compose_path = f'{custom_path}/{COMPOSE_NAME}' compose_path = f'{custom_path}/{COMPOSE_NAME}'
# service name # service name
service_name = f'openhab_{hostname}' service_name = f'openhab_{building}'
# template # template
template = get_service_template(Service.OPENHAB.prefix) template = get_service_template(Service.OPENHAB.prefix)
# only label contraint is building # only label contraint is building
template['deploy']['placement']['constraints'][0] = ( template['deploy']['placement']['constraints'][0] = (
f"{CONSTRAINTS['building']} == {hostname}") f"{CONSTRAINTS['building']} == {building}")
# include in backups of this building # include in backups of this building
template['deploy']['labels'].append(f'backup={hostname}') template['deploy']['labels'].append(f'backup={building}')
# traefik backend # traefik backend
template['deploy']['labels'].append(f'traefik.backend={service_name}') template['deploy']['labels'].append(f'traefik.backend={service_name}')
# traefik frontend domain->openhab # traefik frontend domain->openhab
template['deploy']['labels'].extend( template['deploy']['labels'].extend(
generate_traefik_host_labels(hostname, segment='main')) generate_traefik_host_labels(host, segment='main'))
# traefik frontend subdomain openhab_hostname.* -> openhab # traefik frontend subdomain openhab_hostname.* -> openhab
template['deploy']['labels'].append( template['deploy']['labels'].append(
f'traefik.sub.frontend.rule=HostRegexp:' f'traefik.sub.frontend.rule=HostRegexp:'
...@@ -195,22 +196,22 @@ def add_openhab_service(hostname): ...@@ -195,22 +196,22 @@ def add_openhab_service(hostname):
add_or_update_compose_service(compose_path, service_name, template) add_or_update_compose_service(compose_path, service_name, template)
def add_nodered_service(hostname): def add_nodered_service(building):
"""Generates an nodered entry and adds it to the compose file """Generates an nodered entry and adds it to the compose file
:hostname: names of host that the services is added to :building: name of building that the services is added to
""" """
# compose file # compose file
compose_path = f'{custom_path}/{COMPOSE_NAME}' compose_path = f'{custom_path}/{COMPOSE_NAME}'
# service name # service name
service_name = f'nodered_{hostname}' service_name = f'nodered_{building}'
# template # template
template = get_service_template(Service.NODERED.prefix) template = get_service_template(Service.NODERED.prefix)
# only label contraint is building # only label contraint is building
template['deploy']['placement']['constraints'][0] = ( template['deploy']['placement']['constraints'][0] = (
f"{CONSTRAINTS['building']} == {hostname}") f"{CONSTRAINTS['building']} == {building}")
template['deploy']['labels'].append(f'traefik.backend={service_name}') template['deploy']['labels'].append(f'traefik.backend={service_name}')
template['deploy']['labels'].append(f'backup={hostname}') template['deploy']['labels'].append(f'backup={building}')
template['deploy']['labels'].extend( template['deploy']['labels'].extend(
generate_traefik_path_labels(service_name, segment='main')) generate_traefik_path_labels(service_name, segment='main'))
template['deploy']['labels'].extend( template['deploy']['labels'].extend(
...@@ -223,21 +224,21 @@ def add_nodered_service(hostname): ...@@ -223,21 +224,21 @@ def add_nodered_service(hostname):
add_or_update_compose_service(compose_path, service_name, template) add_or_update_compose_service(compose_path, service_name, template)
def add_mqtt_service(hostname, number=0): def add_mqtt_service(building, number=0):
"""Generates an mqtt entry and adds it to the compose file """Generates an mqtt entry and adds it to the compose file
:hostname: names of host that the services is added to :building: name of building that the services is added to
:number: increment of exposed port to prevent overlaps :number: increment of exposed port to prevent overlaps
""" """
# compose file # compose file
compose_path = f'{custom_path}/{COMPOSE_NAME}' compose_path = f'{custom_path}/{COMPOSE_NAME}'
# service name # service name
service_name = f'mqtt_{hostname}' service_name = f'mqtt_{building}'
# template # template
template = get_service_template(Service.MQTT.prefix) template = get_service_template(Service.MQTT.prefix)
# only label contraint is building # only label contraint is building
template['deploy']['placement']['constraints'][0] = ( template['deploy']['placement']['constraints'][0] = (
f"{CONSTRAINTS['building']} == {hostname}") f"{CONSTRAINTS['building']} == {building}")
# ports incremented by number of services # ports incremented by number of services
template['ports'] = [f'{1883 + number}:1883', f'{9001 + number}:9001'] template['ports'] = [f'{1883 + number}:1883', f'{9001 + number}:9001']
...@@ -248,17 +249,17 @@ def add_mqtt_service(hostname, number=0): ...@@ -248,17 +249,17 @@ def add_mqtt_service(hostname, number=0):
add_or_update_compose_service(compose_path, service_name, template) add_or_update_compose_service(compose_path, service_name, template)
def add_postgres_service(hostname, postfix=None): def add_postgres_service(building, postfix=None):
"""Generates an postgres entry and adds it to the compose file """Generates an postgres entry and adds it to the compose file
:hostname: names of host that the services is added to :building: name of building that the services is added to
:postfix: an identifier for this service :postfix: an identifier for this service
""" """
# compose file # compose file
compose_path = f'{custom_path}/{COMPOSE_NAME}' compose_path = f'{custom_path}/{COMPOSE_NAME}'
# use hostname as postfix when empty # use building as postfix when empty
if postfix is None: if postfix is None:
service_name = f'postgres_{hostname}' service_name = f'postgres_{building}'
else: else:
service_name = f'postgres_{postfix}' service_name = f'postgres_{postfix}'
...@@ -266,7 +267,7 @@ def add_postgres_service(hostname, postfix=None): ...@@ -266,7 +267,7 @@ def add_postgres_service(hostname, postfix=None):
template = get_service_template(Service.POSTGRES.prefix) template = get_service_template(Service.POSTGRES.prefix)
# only label constraint is building # only label constraint is building
template['deploy']['placement']['constraints'][0] = ( template['deploy']['placement']['constraints'][0] = (
f"{CONSTRAINTS['building']} == {hostname}") f"{CONSTRAINTS['building']} == {building}")
# replace volumes with named entries in template # replace volumes with named entries in template
template['volumes'] = generate_named_volumes( template['volumes'] = generate_named_volumes(
...@@ -275,22 +276,22 @@ def add_postgres_service(hostname, postfix=None): ...@@ -275,22 +276,22 @@ def add_postgres_service(hostname, postfix=None):
add_or_update_compose_service(compose_path, service_name, template) add_or_update_compose_service(compose_path, service_name, template)
def add_file_service(hostname): def add_file_service(building):
"""Generates a file manager entry and adds it to the compose file """Generates a file manager entry and adds it to the compose file
:hostname: names of host that the services is added to :building: names of host that the services is added to
""" """
# compose file # compose file
compose_path = f'{custom_path}/{COMPOSE_NAME}' compose_path = f'{custom_path}/{COMPOSE_NAME}'
# service name # service name
service_name = f'{Service.FILES.prefix}_{hostname}' service_name = f'{Service.FILES.prefix}_{building}'
# template # template
template = get_service_template(Service.FILES.prefix) template = get_service_template(Service.FILES.prefix)
# add command that sets base url # add command that sets base url
template['command'] = f'-b /{service_name}' template['command'] = f'-b /{service_name}'
# only label contraint is building # only label contraint is building
template['deploy']['placement']['constraints'][0] = ( template['deploy']['placement']['constraints'][0] = (
f"{CONSTRAINTS['building']} == {hostname}") f"{CONSTRAINTS['building']} == {building}")
template['deploy']['labels'].append(f'traefik.backend={service_name}') template['deploy']['labels'].append(f'traefik.backend={service_name}')
template['deploy']['labels'].extend( template['deploy']['labels'].extend(
generate_traefik_path_labels(service_name, segment='main', generate_traefik_path_labels(service_name, segment='main',
...@@ -298,38 +299,38 @@ def add_file_service(hostname): ...@@ -298,38 +299,38 @@ def add_file_service(hostname):
# attach volumes # attach volumes
volume_base = '/srv/' volume_base = '/srv/'
template['volumes'] = get_attachable_volume_list(volume_base, hostname) template['volumes'] = get_attachable_volume_list(volume_base, building)
add_or_update_compose_service(compose_path, service_name, template) add_or_update_compose_service(compose_path, service_name, template)
def add_volumerize_service(hostname): def add_volumerize_service(building):
"""Generates a volumerize backup entry and adds it to the compose file """Generates a volumerize backup entry and adds it to the compose file
:hostname: names of host that the services is added to :building: names of host that the services is added to
""" """
# compose file # compose file
compose_path = f'{custom_path}/{COMPOSE_NAME}' compose_path = f'{custom_path}/{COMPOSE_NAME}'
# service name # service name
service_name = f'{Service.BACKUP.prefix}_{hostname}' service_name = f'{Service.BACKUP.prefix}_{building}'
# template # template
template = get_service_template(Service.BACKUP.prefix) template = get_service_template(Service.BACKUP.prefix)
# only label contraint is building # only label contraint is building
template['deploy']['placement']['constraints'][0] = ( template['deploy']['placement']['constraints'][0] = (
f"{CONSTRAINTS['building']} == {hostname}") f"{CONSTRAINTS['building']} == {building}")
# attach volumes # attach volumes
volume_base = '/source/' volume_base = '/source/'
template['volumes'].extend( template['volumes'].extend(
get_attachable_volume_list(volume_base, hostname)) get_attachable_volume_list(volume_base, building))
# adjust config # adjust config
config_list = template['configs'] config_list = template['configs']
# get backup entry from configs # get backup entry from configs
index, entry = next((i, c) for i, c in enumerate(config_list) index, entry = next((i, c) for i, c in enumerate(config_list)
if c['source'] == 'backup_config') if c['source'] == 'backup_config')
entry['source'] = f'backup_config_{hostname}' entry['source'] = f'backup_config_{building}'
template['configs'][index] = entry template['configs'][index] = entry
add_or_update_compose_service(compose_path, service_name, template) add_or_update_compose_service(compose_path, service_name, template)
...@@ -358,8 +359,9 @@ def delete_service(service_name): ...@@ -358,8 +359,9 @@ def delete_service(service_name):
# Functions to extract information # Functions to extract information
def get_current_services(placement=None): def get_current_services(placement=None):
"""Gets a list of currently used services """Gets a list of currently used services may be restricted to a placement
:placement: placement contraint the service shall match
:returns: list of current services :returns: list of current services
""" """
# compose file # compose file
...@@ -376,6 +378,26 @@ def get_current_services(placement=None): ...@@ -376,6 +378,26 @@ def get_current_services(placement=None):
return service_names return service_names
def get_current_building_constraints():
"""Gets a list of currently used building constraints
:returns: set of current buildings
"""
# compose file
compose_path = f'{custom_path}/{COMPOSE_NAME}'
with open(compose_path, 'r') as compose_f:
# load compose file
compose = yaml.load(compose_f)
# generate list of buildings
building_names = set()
for (name, entry) in compose['services'].items():
building = get_building_of_entry(entry)
if building:
building_names.add(building)
return building_names
def get_building_of_entry(service_dict): def get_building_of_entry(service_dict):
"""Extract the configured building constraint from an yaml service entry """Extract the configured building constraint from an yaml service entry
...@@ -425,15 +447,15 @@ def get_service_volumes(service_name): ...@@ -425,15 +447,15 @@ def get_service_volumes(service_name):
# Helper functions # Helper functions
def get_attachable_volume_list(volume_base, host): def get_attachable_volume_list(volume_base, building):
"""Get a list of volumes from a host that can be attatched for file acccess """Get a list of volumes from a building that can be attatched for file acccess
:volume_base: Base path of volumes :volume_base: Base path of volumes
:host: host to consider :building: building to consider
:returns: list of attachable volume entries :returns: list of attachable volume entries
""" """
volume_list = [] volume_list = []
host_services = get_current_services(host) host_services = get_current_services(building)
for host_service in host_services: for host_service in host_services:
name, instance = get_service_entry_info(host_service) name, instance = get_service_entry_info(host_service)
volume_service = Service.service_by_prefix(name) volume_service = Service.service_by_prefix(name)
...@@ -713,9 +735,10 @@ def generate_traefik_user_line(username, password): ...@@ -713,9 +735,10 @@ def generate_traefik_user_line(username, password):
return line return line
def generate_pb_framr_entry(host, service): def generate_pb_framr_entry(building, host, service):
"""Generates a single entry of the framr file """Generates a single entry of the framr file
:building: building this entry is intended for
:host: host this entry is intended for :host: host this entry is intended for
:service: entry from service enum :service: entry from service enum
:returns: a dict fitting the asked entry :returns: a dict fitting the asked entry
...@@ -727,7 +750,7 @@ def generate_pb_framr_entry(host, service): ...@@ -727,7 +750,7 @@ def generate_pb_framr_entry(host, service):
entry['url'] = f'http://{host}/' entry['url'] = f'http://{host}/'
pass pass
else: else:
entry['url'] = f'/{service.prefix}_{host}/' entry['url'] = f'/{service.prefix}_{building}/'
entry['icon'] = service.icon entry['icon'] = service.icon
return entry return entry
...@@ -852,28 +875,30 @@ def generate_traefik_file(username, password): ...@@ -852,28 +875,30 @@ def generate_traefik_file(username, password):
create_or_replace_config_file(EDIT_FILES['traefik_users'], file_content) create_or_replace_config_file(EDIT_FILES['traefik_users'], file_content)
def generate_volumerize_files(hosts): def generate_volumerize_files(host_entries):
"""Generates config for volumerize backups """Generates config for volumerize backups
:hosts: names of backup hosts :host_entries: dickt of host entries
""" """
compose_path = f'{custom_path}/{COMPOSE_NAME}' compose_path = f'{custom_path}/{COMPOSE_NAME}'
# create one config per host # create one config per host
for h in hosts: for h in host_entries:
configs = [] configs = []
# Each host knows other hosts # Each host knows other hosts
for t in hosts: for t in host_entries:
host_config = { host_config = {
'description': f'Backup Server on {t}', 'description': f"'Backup Server on {t['building_name']}",
'url': f'sftp://ohadmin@sftp_{t}:' 'url': f"sftp://ohadmin@sftp_{t['building_id']}:"
f'//home/ohadmin/backup_data/backup/{h}' f"//home/ohadmin/backup_data/backup/{h['building_id']}"
} }
configs.append(host_config) configs.append(host_config)
config_file = f"{EDIT_FILES['backup_config']}_{h}.json" config_file = f"{EDIT_FILES['backup_config']}_{h['building_id']}.json"
create_or_replace_config_file(config_file, configs, json=True) create_or_replace_config_file(config_file, configs, json=True)
add_config_entry( add_config_entry(
compose_path, f'backup_config_{h}', f"./{config_file}") compose_path,
f"backup_config_{h['building_id']}",
f"./{config_file}")
def generate_pb_framr_file(frames): def generate_pb_framr_file(frames):
...@@ -885,8 +910,8 @@ def generate_pb_framr_file(frames): ...@@ -885,8 +910,8 @@ def generate_pb_framr_file(frames):
for f in frames: for f in frames:
building = { building = {
'instance': f['building'], 'instance': f['building_name'],
'entries': [generate_pb_framr_entry(f['host'], s) 'entries': [generate_pb_framr_entry(f['building_id'], f['host'], s)
for s in f['services'] if s.frontend] for s in f['services'] if s.frontend]
} }
configs.append(building) configs.append(building)
...@@ -1472,20 +1497,23 @@ def init_menu(args): ...@@ -1472,20 +1497,23 @@ def init_menu(args):
generate_postgres_files(username, password) generate_postgres_files(username, password)
generate_mosquitto_file(username, password) generate_mosquitto_file(username, password)
generate_traefik_file(username, password) generate_traefik_file(username, password)
generate_volumerize_files(hosts)
generate_filebrowser_file(username, password) generate_filebrowser_file(username, password)
generate_id_rsa_files() generate_id_rsa_files()
generate_host_key_files(hosts)
frames = [] frames = []
for i, host in enumerate(hosts): for i, host in enumerate(hosts):
building, services = init_machine_menu(host, i) building_id, building_name, services = init_machine_menu(host, i)
frames.append({'host': host, frames.append({'host': host,
'building': building, 'services': services}) 'building_id': building_id,
'building_name': building_name,
'services': services})
# When frames is not empty generate frame config # When frames is not empty generate frame config
if frames: if frames:
generate_pb_framr_file(frames) generate_pb_framr_file(frames)
generate_volumerize_files(frames)
building_ids = [f['building_id'] for f in frames]
generate_host_key_files(building_ids)
# print(answers) # print(answers)
print(f"Configuration files for {stack_name} generated in {custom_path}") print(f"Configuration files for {stack_name} generated in {custom_path}")
...@@ -1503,29 +1531,36 @@ def init_machine_menu(host, increment): ...@@ -1503,29 +1531,36 @@ def init_machine_menu(host, increment):
:host: docker-machine host :host: docker-machine host
:increment: incrementing number to ensure ports are unique :increment: incrementing number to ensure ports are unique
:return: choosen building name and services :return: choosen building id, name and services
""" """
# Print divider
print('----------')
# Prompt for services # Prompt for services
building = qust.text(f'Choose a name for building on server {host}', building_id = qust.text(
default=f'{host}', style=st).ask() f'Choose an identifier for the building on server {host} '
'(lowercase no space)',
default=f'{host}', style=st).ask()
building = qust.text(
f'Choose a display name for building on server {host}',
default=f'{host.capitalize()}', style=st).ask()
services = qust.checkbox(f'What services shall {host} provide?', services = qust.checkbox(f'What services shall {host} provide?',
choices=generate_cb_service_choices(checked=True), choices=generate_cb_service_choices(checked=True),
style=st).ask() style=st).ask()
if Service.OPENHAB in services: if Service.OPENHAB in services:
add_openhab_service(host) add_openhab_service(building_id, host)
if Service.NODERED in services: if Service.NODERED in services:
add_nodered_service(host) add_nodered_service(building_id)
if Service.MQTT in services: if Service.MQTT in services:
add_mqtt_service(host, increment) add_mqtt_service(building_id, increment)
if Service.POSTGRES in services: if Service.POSTGRES in services:
add_postgres_service(host) add_postgres_service(building_id)
if Service.BACKUP in services: if Service.BACKUP in services:
add_volumerize_service(host) add_volumerize_service(building_id)
if Service.FILES in services: if Service.FILES in services:
add_file_service(host) add_file_service(building_id)
if Service.SFTP in services: if Service.SFTP in services:
add_sftp_service(host, increment) add_sftp_service(building_id, increment)
return building, services return building_id, building, services
# *** Exec Menu Entries *** # *** Exec Menu Entries ***
...@@ -1779,6 +1814,8 @@ def backup_menu(args): ...@@ -1779,6 +1814,8 @@ def backup_menu(args):
elif "Restore" in choice: elif "Restore" in choice:
restore_backup_menu() restore_backup_menu()
print("Restore") print("Restore")
else:
print(get_current_building_constraints())
def execute_backup_menu(): def execute_backup_menu():
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment