Skip to content
This repository has been archived by the owner on Jun 11, 2023. It is now read-only.

Commit

Permalink
Add handle_request for MotherboardUpdateRequest
Browse files Browse the repository at this point in the history
  • Loading branch information
renatomassaro committed Dec 14, 2017
1 parent 6629945 commit 6ed5c69
Show file tree
Hide file tree
Showing 12 changed files with 569 additions and 58 deletions.
14 changes: 6 additions & 8 deletions lib/server/action/flow/server.ex
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ defmodule Helix.Server.Action.Flow.Server do

def update_mobo(
server = %Server{},
cur_mobo_data,
motherboard,
new_mobo_data,
entity_ncs,
relay)
Expand All @@ -56,21 +56,19 @@ defmodule Helix.Server.Action.Flow.Server do

flowing do
with \
{:ok, new_mobo, events} <-
MotherboardAction.update(
cur_mobo_data, new_mobo_data, entity_ncs
),
{:ok, new_motherboard, events} <-
MotherboardAction.update(motherboard, new_mobo_data, entity_ncs),
on_success(fn -> Event.emit(events, from: relay) end),

{:ok, new_server} <- update_server_mobo(server, new_mobo_id)
do
{:ok, new_server, new_mobo}
{:ok, new_server, new_motherboard}
end
end
end

defp update_server_mobo(%Server{motherboard_id: mobo_id}, mobo_id),
do: {:ok, mobo_id}
defp update_server_mobo(server = %Server{motherboard_id: mobo_id}, mobo_id),
do: {:ok, server}
defp update_server_mobo(server, nil),
do: ServerAction.detach(server)
defp update_server_mobo(server, mobo_id),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
# TODO: Move to motherboard action (outside flow)
defmodule Helix.Server.Action.Motherboard.Update do

import HELL.Macros

alias Helix.Network.Action.Network, as: NetworkAction
alias Helix.Network.Model.Network
alias Helix.Network.Query.Network, as: NetworkQuery
alias Helix.Server.Action.Component, as: ComponentAction
alias Helix.Server.Internal.Motherboard, as: MotherboardInternal
alias Helix.Server.Query.Component, as: ComponentQuery
alias Helix.Server.Repo, as: ServerRepo

alias Helix.Server.Query.Component, as: ComponentQuery

alias Helix.Server.Internal.Motherboard, as: MotherboardInternal
@internet_id NetworkQuery.internet().network_id

def update(nil, mobo_data, entity_ncs) do
{:ok, new_mobo} =
Expand Down Expand Up @@ -43,22 +44,22 @@ defmodule Helix.Server.Action.Motherboard.Update do
defp update_network_connections(mobo_data, entity_ncs) do
# Secondary index used to figure out whether a specific NIP was specified on
# `mobo_data.network_connections`.
assigned_nips =
Enum.reduce(mobo_data.network_connections, [], fn {_, nip}, acc ->
acc ++ [nip]
end)
# assigned_nips =
# Enum.reduce(mobo_data.network_connections, [], fn {_, nip}, acc ->
# acc ++ [nip]
# end)

ncs = mobo_data.network_connections

entity_ncs

# Get the required operations we may have to do on NetworkConnections...
|> Enum.reduce([], fn nc, acc ->
cond do
# The NIC already has an NC attached to it
Map.has_key?(mobo_data.network_connections, nc.nic_id) ->
nip = mobo_data.network_connections[nc.nic_id]

mobo_nc = has_nic?(ncs, nc.nic_id) ->
# The given NC is the same as before; we don't have to do anything
if {nc.network_id, nc.ip} == nip do
if nc == mobo_nc.network_connection do
acc

# There will be a new NC attached to this NIC, so we have to
Expand All @@ -73,31 +74,37 @@ defmodule Helix.Server.Action.Motherboard.Update do
# The current NC nic is not in use, but its nip is being assigned.
# This means the NC will start being used, so we need to link it to
# the underlying NIC.
{nc.network_id, nc.ip} in assigned_nips ->
{nic_id, _} =
mobo_data.network_connections
|> Enum.find(fn {_, {network_id, ip}} ->
network_id == nc.network_id and ip == nc.ip
end)

acc ++ [{:set_nic, nc, nic_id}]
mobo_nc = has_nip?(ncs, nc.network_id, nc.ip) ->
acc ++ [{:set_nic, nc, mobo_nc.nic_id}]

# This NC is not modified at all by the mobo update
true ->
acc

end
end)

# Perform those NetworkConnection operations
|> Enum.each(&perform_network_op/1)
end

defp has_nic?(ncs, nic_id),
do: Enum.find(ncs, &(&1.nic_id == nic_id))

defp has_nip?(ncs, network_id, ip),
do: Enum.find(ncs, &(&1.network_id == network_id and &1.ip == ip))

defp perform_network_op({:nilify_nic, nc = %Network.Connection{}}),
do: {:ok, _} = NetworkAction.Connection.update_nic(nc, nil)
defp perform_network_op({:set_nic, nc = %Network.Connection{}, nic_id}) do
nic = ComponentQuery.fetch(nic_id)

{:ok, _} = NetworkAction.Connection.update_nic(nc, nic)

# Update the NIC custom
# Note that by default the NIC is assumed to belong to the internet, that's
# why we'll only update it in case it's on a different network.
unless nc.network_id == @internet_id do
ComponentAction.NIC.update_network_id(nic, nc.network_id)
end
end
end
16 changes: 12 additions & 4 deletions lib/server/henforcer/component.ex
Original file line number Diff line number Diff line change
Expand Up @@ -94,17 +94,25 @@ defmodule Helix.Server.Henforcer.Component do
init = {{true, %{}}, nil}

network_connections
|> Enum.reduce_while(init, fn {_nic_id, nip}, {{true, acc}, cache} ->
|> Enum.reduce_while(init, fn {nic_id, nip}, {{true, acc}, cache} ->
{network_id, ip} = nip

with \
{true, r1} <- EntityHenforcer.owns_nip?(entity, network_id, ip, cache)
do
acc_nc = Map.get(acc, :network_connections, [])

new_entry =
%{
nic_id: nic_id,
network_id: network_id,
ip: ip,
network_connection: r1.network_connection
}

new_acc =
acc
|> put_in([:network_connections], acc_nc ++ [r1.network_connection])
|> put_in([:network_connections], acc_nc ++ [new_entry])
|> put_in(
[:entity_network_connections], r1.entity_network_connections
)
Expand All @@ -120,7 +128,7 @@ defmodule Helix.Server.Henforcer.Component do

with \
{true, r0} <- component_exists?(mobo_id),
mobo = r0.component,
{r0, mobo} = get_and_replace(r0, :component, :mobo),

# Make sure user is plugging components into a motherboard
{true, _} <- is_motherboard?(mobo),
Expand All @@ -143,7 +151,7 @@ defmodule Helix.Server.Henforcer.Component do
# The mobo must have at least one public NC assigned to it
{true, _} <- has_public_nip?(r2.network_connections)
do
reply_ok(relay([r1, r2]))
reply_ok(relay([r0, r1, r2]))
else
error ->
error
Expand Down
19 changes: 19 additions & 0 deletions lib/server/public/server.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ defmodule Helix.Server.Public.Server do
alias Helix.Server.Model.Server
alias Helix.Server.Action.Flow.Server, as: ServerFlow
alias Helix.Server.Public.Index, as: ServerIndex
alias Helix.Server.Query.Motherboard, as: MotherboardQuery

@spec connect_to_server(Server.id, Server.id, [Server.id]) ::
{:ok, Tunnel.t}
Expand Down Expand Up @@ -39,6 +40,24 @@ defmodule Helix.Server.Public.Server do
end
end

def update_mobo(server, {mobo, components, ncs}, entity_ncs, relay) do
motherboard =
if server.motherboard_id do
MotherboardQuery.fetch(server.motherboard_id)
else
nil
end

mobo_data =
%{
mobo: mobo,
components: components,
network_connections: ncs
}

ServerFlow.update_mobo(server, motherboard, mobo_data, entity_ncs, relay)
end

defdelegate set_hostname(server, hostname, relay),
to: ServerFlow

Expand Down
29 changes: 17 additions & 12 deletions lib/server/websocket/channel/server.ex
Original file line number Diff line number Diff line change
Expand Up @@ -127,18 +127,23 @@ channel Helix.Server.Websocket.Channel.Server do
topic "config.check", ConfigCheckRequest

@doc """
{} => mobo.detach
\/ update
{
"motherboard_id" : "motherboard_id"
, "slots" :
{ "slot_id_a" : "component_id" , "slot_id_b" : null}
, "network_connections" :
{ "component_id" :
{ "ip" : "ip" , "network_id" : "network_id"}
}
}
Errors:
Henforcer:
- component_not_found: One of the specified components were not found
- motherboard_wrong_slot_type: Buraco errado
- motherboard_bad_slot: Specified invalid slot ID
- component_not_belongs: One of the components do not belong to the player
- motherboard_missing_initial_components: So large it's self explanatory
- network_connection_not_belongs: One of the NCs do not belong to the player
- motherboard_missing_public_nip: Mobos must have at least one public NIP
- component_not_motherboard: Wrong tool for the job
Input validation:
- bad_slot_data: slot data (input) is invalid
- bad_network_connections: network connections data (input) is invalid
- bad_src: this request may only be run on `local` channels
+ base errors
"""
topic "motherboard.update", MotherboardUpdateRequest

Expand Down
50 changes: 46 additions & 4 deletions lib/server/websocket/requests/motherboard_update.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ import Helix.Websocket.Request

request Helix.Server.Websocket.Requests.MotherboardUpdate do

import HELL.Macros

alias HELL.IPv4
alias HELL.Utils
alias Helix.Network.Model.Network
alias Helix.Server.Henforcer.Component, as: ComponentHenforcer
alias Helix.Server.Henforcer.Server, as: ServerHenforcer
alias Helix.Server.Model.Component
alias Helix.Server.Public.Server, as: ServerPublic

Expand Down Expand Up @@ -60,10 +64,50 @@ request Helix.Server.Websocket.Requests.MotherboardUpdate do
end
end

def check_permissions(request, socket) do
def check_permissions(request = %{params: %{cmd: :update}}, socket) do
gateway_id = socket.assigns.gateway.server_id
entity_id = socket.assigns.gateway.entity_id
mobo_id = request.params.mobo_id
slots = request.params.slots
ncs = request.params.network_connections

with \
{true, r0} <- ServerHenforcer.server_exists?(gateway_id),
{true, r1} <-
ComponentHenforcer.can_update_mobo?(entity_id, mobo_id, slots, ncs)
do
meta = %{
server: r0.server,
mobo: r1.mobo,
components: r1.components,
owned_components: r1.owned_components,
network_connections: r1.network_connections,
entity_network_connections: r1.entity_network_connections
}

update_meta(request, meta, reply: true)
else
{false, reason, _} ->
reply_error(request, reason)
end
end

def handle_request(request, socket) do
def handle_request(request = %{params: %{cmd: :update}}, socket) do
server = request.meta.server
mobo = request.meta.mobo
components = request.meta.components
ncs = request.meta.network_connections
entity_ncs = request.meta.entity_network_connections
relay = request.relay

# Updates mobo asynchronously
hespawn fn ->
ServerPublic.update_mobo(
server, {mobo, components, ncs}, entity_ncs, relay
)
end

reply_ok(request)
end

render_empty()
Expand All @@ -88,7 +132,6 @@ request Helix.Server.Websocket.Requests.MotherboardUpdate do
end
end

# TODO: Move to a SpecableHelper or something like that
defp cast_slots(nil),
do: :bad_slots
defp cast_slots(slots) do
Expand Down Expand Up @@ -143,5 +186,4 @@ request Helix.Server.Websocket.Requests.MotherboardUpdate do
:error
end
end

end
Loading

0 comments on commit 6ed5c69

Please sign in to comment.