I am working in a django webpage, and I was asked to do an async check for the netplan in the server the page is hosted after doing modifications, I have this view:
async def network_config_edit_view(request):
path = '/etc/netplan/00-network.yaml'
backup_path = '/etc/netplan/00-network.yaml.backup'
www_data_uid = 33
www_data_gid = 33
try:
if await sync_to_async(os.path.exists, thread_sensitive=True)(backup_path):
await sync_to_async(os.remove, thread_sensitive=True)(backup_path)
await sync_to_async(shutil.copy, thread_sensitive=True)(path, backup_path)
print(f"Backup of the original file created at {backup_path}.")
except Exception as e:
print(f"Error creating backup file: {e}")
config_data = await sync_to_async(read_network_config, thread_sensitive=True)(path)
if request.method == 'POST':
form = NetworkConfigForm(request.POST)
if form.is_valid():
cleaned_data = form.cleaned_data
data_to_save = {
'ipv4_addresses': [cleaned_data.get('ipv4_address')] if cleaned_data.get('ipv4_address') else [],
'ipv6_addresses': [cleaned_data.get('ipv6_address')] if cleaned_data.get('ipv6_address') else [],
'ipv4_gateway': cleaned_data.get('ipv4_gateway', ''),
'ipv6_gateway': cleaned_data.get('ipv6_gateway', ''),
'dns_addresses': [addr.strip() for addr in cleaned_data.get('ipv4_dns', '').split(',') if addr.strip()] +
[addr.strip() for addr in cleaned_data.get('ipv6_dns', '').split(',') if addr.strip()]
}
try:
await sync_to_async(save_to_yaml, thread_sensitive=True)(data_to_save, file_path=path)
await sync_to_async(os.chown, thread_sensitive=True)(path, www_data_uid, www_data_gid)
await sync_to_async(os.chmod, thread_sensitive=True)(path, 0o664)
print("YAML file has been saved.")
messages.success(request, "The new configuration has been saved successfully.")
except Exception as e:
print(f"Error saving YAML file: {e}")
messages.error(request, f"Error saving YAML file: {e}")
context = {
'form': form,
**admin.site.each_context(request),
'error': f"Error saving YAML file: {e}",
}
html = render_to_string('admin/network_config_edit.html', context)
return HttpResponse(html)
if await apply_netplan():
if await check_network_status():
await sync_to_async(restart_services, thread_sensitive=True)()
messages.success(request, "Services restarted successfully.")
else:
messages.error(request, "Network check failed after applying netplan.")
context = {
'form': form,
**admin.site.each_context(request),
'error': "Network check failed after applying netplan.",
}
html = render_to_string('admin/network_config_edit.html', context)
return HttpResponse(html)
else:
messages.error(request, "Failed to apply netplan.")
context = {
'form': form,
**admin.site.each_context(request),
'error': "Failed to apply netplan.",
}
html = render_to_string('admin/network_config_edit.html', context)
return HttpResponse(html)
else:
form = NetworkConfigForm(initial=config_data)
context = {
'form': form,
**admin.site.each_context(request),
}
html = render_to_string('admin/network_config_edit.html', context)
return HttpResponse(html)
and these functions:
async def apply_netplan():
process = await asyncio.create_subprocess_shell('sudo netplan apply', stdout = subprocess.PIPE, stderr = subprocess.PIPE)
stdout, stderr = await process.communicate()
if process.returncode == 0 :
print("Netplan applied successfully.")
return True
else:
print(f"Netplan apply failed: {stderr.decode()}")
return False
async def check_network_status():
for _ in range(10):
result = await asyncio.create_subprocess_shell(
'ping -c 1 8.8.8.8',
stdout = subprocess.PIPE,
stderr = subprocess.PIPE)
stdout, stderr = await result.communicate()
if result.returncode == 0:
print("Network is up.")
return True
await asyncio.sleep(5)
return False
def restart_services():
try:
result = subprocess.run(['systemctl', 'restart', 'gunicorn'], capture_output=True, text=True, check=True)
print("Gunicorn service started successfully.")
except subprocess.CalledProcessError as e:
print(f"Error starting Gunicorn service: {e.stderr}")
raise e
I have no clue what might be wrong here, do you guys have any suggestion?
The main idea is a user can make modifications in the netplan by editing the yaml file through the page, it saves the new conf and applies netplan apply and restarts gunicorn, but when I go into the editing page, I get the error in the title.
Ruben San Martin is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.