Packages
livebook
0.5.2
0.19.8
0.19.7
0.19.6
0.19.5
0.19.4
0.19.3
0.19.2
0.19.1
0.19.0
0.18.6
0.18.5
0.18.4
0.18.3
0.18.2
0.18.1
0.18.0
0.17.3
0.17.2
0.17.1
0.17.0
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.7
0.14.6
0.14.5
0.14.4
0.14.3
0.14.2
0.14.1
0.14.0
0.14.0-rc.1
0.14.0-rc.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.1
0.12.0
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.2
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.6.3
0.6.2
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.3.2
0.3.1
0.3.0
0.2.3
0.2.2
0.2.1
0.2.0
0.1.2
0.1.1
0.1.0
Automate code & data workflows with interactive notebooks
Current section
Files
Jump to
Current section
Files
lib/livebook/application.ex
defmodule Livebook.Application do
# See https://hexdocs.pm/elixir/Application.html
# for more information on OTP Applications
@moduledoc false
use Application
def start(_type, _args) do
ensure_distribution!()
validate_hostname_resolution!()
set_cookie()
children =
[
# Start the Telemetry supervisor
LivebookWeb.Telemetry,
# Start the PubSub system
{Phoenix.PubSub, name: Livebook.PubSub},
# Periodid measurement of system resources
Livebook.SystemResources,
# Start the tracker server on this node
{Livebook.Tracker, pubsub_server: Livebook.PubSub},
# Start the supervisor dynamically managing sessions
{DynamicSupervisor, name: Livebook.SessionSupervisor, strategy: :one_for_one},
# Start the server responsible for associating files with sessions
Livebook.Session.FileGuard,
# Start the Node Pool for managing node names
Livebook.Runtime.NodePool,
# Start the unique task dependencies
Livebook.UniqueTask,
# Start the Endpoint (http/https)
# We skip the access url as we do our own logging below
{LivebookWeb.Endpoint, log_access_url: false}
] ++ app_specs()
opts = [strategy: :one_for_one, name: Livebook.Supervisor]
with {:ok, _} = result <- Supervisor.start_link(children, opts) do
clear_env_vars()
display_startup_info()
result
end
end
# Tell Phoenix to update the endpoint configuration
# whenever the application is updated.
def config_change(changed, _new, removed) do
LivebookWeb.Endpoint.config_change(changed, removed)
:ok
end
defp ensure_distribution!() do
unless Node.alive?() do
case System.cmd("epmd", ["-daemon"]) do
{_, 0} ->
:ok
_ ->
Livebook.Config.abort!("""
could not start epmd (Erlang Port Mapper Driver). Livebook uses epmd to \
talk to different runtimes. You may have to start epmd explicitly by calling:
epmd -daemon
Or by calling:
elixir --sname test -e "IO.puts node()"
Then you can try booting Livebook again
""")
end
{type, name} = get_node_type_and_name()
case Node.start(name, type) do
{:ok, _} ->
:ok
{:error, reason} ->
Livebook.Config.abort!("could not start distributed node: #{inspect(reason)}")
end
end
end
import Record
defrecordp :hostent, Record.extract(:hostent, from_lib: "kernel/include/inet.hrl")
# See https://github.com/livebook-dev/livebook/issues/302
defp validate_hostname_resolution!() do
unless Livebook.Config.longname() do
hostname = Livebook.Utils.node_host() |> to_charlist()
case :inet.gethostbyname(hostname) do
{:error, :nxdomain} ->
invalid_hostname!("your hostname \"#{hostname}\" does not resolve to an IP address")
# We only try the first address, so that's the one we validate.
{:ok, hostent(h_addrtype: :inet, h_addr_list: [address | _])} ->
unless inet_loopback?(address) or inet_if?(address) do
invalid_hostname!(
"your hostname \"#{hostname}\" does not resolve to a loopback address (127.0.0.0/8)"
)
end
_ ->
:ok
end
end
end
defp inet_loopback?(address) do
match?({127, _, _, _}, address)
end
defp inet_if?(address) do
case :inet.getifaddrs() do
{:ok, addrs} -> Enum.any?(addrs, fn {_name, flags} -> {:addr, address} in flags end)
_ -> false
end
end
defp invalid_hostname!(prelude) do
Livebook.Config.abort!("""
#{prelude}, which indicates something wrong in your OS configuration.
Make sure your computer's name resolves locally or start Livebook using a long distribution name. If you are using Livebook's CLI, you can:
livebook server --name livebook@127.0.0.1
If you are running it from source, do instead:
MIX_ENV=prod elixir --name livebook@127.0.0.1 -S mix phx.server
""")
end
defp set_cookie() do
cookie = Application.fetch_env!(:livebook, :cookie)
Node.set_cookie(cookie)
end
defp get_node_type_and_name() do
Application.get_env(:livebook, :node) || {:shortnames, random_short_name()}
end
defp random_short_name() do
:"livebook_#{Livebook.Utils.random_short_id()}"
end
defp display_startup_info() do
if Phoenix.Endpoint.server?(:livebook, LivebookWeb.Endpoint) do
IO.puts("[Livebook] Application running at #{LivebookWeb.Endpoint.access_url()}")
end
end
defp clear_env_vars() do
for {var, _} <- System.get_env(), config_env_var?(var) do
System.delete_env(var)
end
end
defp config_env_var?("LIVEBOOK_" <> _), do: true
defp config_env_var?("RELEASE_" <> _), do: true
defp config_env_var?(_), do: false
if Mix.target() == :app do
defp app_specs, do: [LivebookApp]
else
defp app_specs, do: []
end
end