Current section

Files

Jump to
libsniffle src ls_vm.erl
Raw

src/ls_vm.erl

-module(ls_vm).
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
-endif.
-export([
get/1, get_docker/1, get_hostname/2,
dry_run/3, create/3, delete/1, delete/2, store/1, store/2,
register/2, unregister/1,
state/2,
creating/2,
update/3, update/4,
add_nic/2, remove_nic/2, primary_nic/2,
set_config/2,
set_info/2,
set_service/2,
set_backup/2,
set_snapshot/2,
set_metadata/2,
hostname/3,
log/2,
snapshot/2, delete_snapshot/2, rollback_snapshot/2,
commit_snapshot_rollback/2, promote_snapshot/3,
incremental_backup/4, full_backup/3,
restore_backup/2, restore_backup/3, restore_backup/4, restore_backup/5,
delete_backup/3,
service_enable/2, service_disable/2, service_clear/2,
service_refresh/2, service_restart/2,
add_fw_rule/2, remove_fw_rule/2,
list/0, list/2, stream/3,
start/1, stop/1, stop/2,
reboot/1, reboot/2,
owner/2, owner/3
]).
-define(UUID, <<UUID:36/binary>>).
%%%===================================================================
%%% VM Functions
%%%===================================================================
%%--------------------------------------------------------------------
%% @doc Adds a new firewall rule to a VM.
%% @end
%%--------------------------------------------------------------------
-spec add_fw_rule(VM::fifo:vm_id(), Hypervisor::fifo:fw_rule()) ->
ok |
{'error', 'no_servers'}.
add_fw_rule(UUID, Rule) ->
send({vm, fw, add, UUID, Rule}).
%%--------------------------------------------------------------------
%% @doc Deletes a firewall rule from a VM.
%% @end
%%--------------------------------------------------------------------
-spec remove_fw_rule(VM::fifo:vm_id(), Hypervisor::fifo:fw_rule()) ->
ok |
{'error', 'no_servers'}.
remove_fw_rule(UUID, Rule) ->
send({vm, fw, remove, UUID, Rule}).
%%--------------------------------------------------------------------
%% @doc Initiates the creating a new VM, this will just return the
%% UUID progress is directy written to the object in the database.
%% @end
%%--------------------------------------------------------------------
-spec create(PackageID::fifo:package_id(),
DatasetID::fifo:package_id() |{docker, binary()},
Config::fifo:attr_list()) ->
{error, no_servers} |
{ok, UUID::binary()}.
create(PackageID, DatasetID, Config) ->
send({vm, create, PackageID, DatasetID, Config}).
%%--------------------------------------------------------------------
%% @doc Initiates the creating a new VM, this will just return the
%% UUID progress is directy written to the object in the database.
%% @end
%%--------------------------------------------------------------------
-spec dry_run(PackageID::binary(), DatasetID::binary(),
Config::maps:map()) ->
{error, no_servers} |
{ok, success|failed}.
dry_run(PackageID, DatasetID, Config) ->
send({vm, dry_run, PackageID, DatasetID, Config}).
%%--------------------------------------------------------------------
%% @doc Registeres an existing VM with sniffle.
%% @end
%%--------------------------------------------------------------------
-spec register(VM::fifo:vm_id(), Hypervisor::fifo:hypervisor_id()) ->
ok |
{'error', 'no_servers'}.
register(VM, Hypervisor) when
is_binary(VM),
is_binary(Hypervisor) ->
send({vm, register, VM, Hypervisor}).
%%--------------------------------------------------------------------
%% @doc Unregisteres a VM from the database, this does not include
%% deleting it from the hypervisor.
%% @end
%%--------------------------------------------------------------------
-spec unregister(VM::fifo:vm_id()) ->
ok |
not_found |
{'error', 'no_servers'}.
unregister(VM) when
is_binary(VM) ->
send({vm, unregister, VM}).
%%--------------------------------------------------------------------
%% @doc Reads the VM attribute from the database.
%% @end
%%--------------------------------------------------------------------
-spec get(VM::fifo:vm_id()) ->
not_found |
{ok, fifo:vm()} |
{'error', 'no_servers'}.
get(VM) when
is_binary(VM) ->
send({vm, get, VM}).
%%--------------------------------------------------------------------
%% @doc Reads the VM attribute from the database.
%% @end
%%--------------------------------------------------------------------
-spec get_docker(VM::binary()) ->
not_found |
{ok, fifo:vm()} |
{'error', 'no_servers'}.
get_docker(VM) when
is_binary(VM) ->
send({vm, get, docker, VM}).
%%--------------------------------------------------------------------
%% @doc Looks up vm's by hostname and organisation
%% @end
%%--------------------------------------------------------------------
-spec get_hostname(Hostname::binary(), Org::binary()) ->
not_found |
{ok, term()} | %% this is a ft_hostname:hostname().
{'error', 'no_servers'}.
get_hostname(Hostname, Org) when
is_binary(Hostname),
is_binary(Org) ->
send({vm, get, hostname, Hostname, Org}).
%%--------------------------------------------------------------------
%% @doc Sets the hostname on an interface.
%% @end
%%--------------------------------------------------------------------
-spec hostname(Vm::binary(), Interface::binary(), Hostname::binary()) ->
not_found |
ok |
{'error', 'no_servers'}.
hostname(Vm, Interface, Hostname) when
is_binary(Vm),
is_binary(Interface),
is_binary(Hostname) ->
send({vm, hostname, Vm, Interface, Hostname}).
%%--------------------------------------------------------------------
%% @doc Starts a VM on the hypervisor.
%% @end
%%--------------------------------------------------------------------
-spec start(VM::fifo:vm_id()) ->
ok | not_found |
{error, creating} |
{error, not_deployed} |
{'error', 'no_servers'}.
start(VM) when
is_binary(VM) ->
send({vm, start, VM}).
%%--------------------------------------------------------------------
%% @doc Stops a VM on the hypervisor.
%% @end
%%--------------------------------------------------------------------
-spec stop(VM::fifo:vm_id()) ->
ok | not_found |
{'error', 'no_servers'}.
stop(VM) when is_binary(VM) ->
stop(VM, []).
%%--------------------------------------------------------------------
%% @doc Stops a VM on the hypervisor and allows passing options like
%% forced stop.
%% @end
%%--------------------------------------------------------------------
-spec stop(VM::fifo:vm_id(),
Options::[atom() | {atom(), term()}]) ->
ok | not_found |
{'error', 'no_servers'}.
stop(VM, []) when
is_binary(VM)->
send({vm, stop, VM});
stop(VM, [force]) when
is_binary(VM)->
send({vm, stop, force, VM}).
%%--------------------------------------------------------------------
%% @doc Restarts a VM on the hypervisor
%% @end
%%--------------------------------------------------------------------
-spec reboot(VM::fifo:vm_id()) ->
ok | not_found |
{'error', 'no_servers'}.
reboot(VM) when
is_binary(VM) ->
reboot(VM, []).
%%--------------------------------------------------------------------
%% @doc Restarts a VM on the hypervisor and allows passing options like
%% forced restart.
%% @end
%%--------------------------------------------------------------------
-spec reboot(VM::fifo:vm_id(),
Options::[atom() | {atom(), term()}]) ->
ok | not_found |
{'error', 'no_servers'}.
reboot(VM, []) when
is_binary(VM) ->
send({vm, reboot, VM});
reboot(VM, [force]) when
is_binary(VM) ->
send({vm, reboot, force, VM}).
%%--------------------------------------------------------------------
%% @doc Triggers a delete, this does not remove the VM from the
%% database instead just pokes the hypervisor which, when the delete
%% was successful calls a unregister.
%% @end
%%--------------------------------------------------------------------
-spec delete(User::fifo:vm_id() | undefined,
VM::fifo:vm_id()) ->
ok | not_found |
{error, creating} |
{error, no_servers}.
delete(User, VM) when
is_binary(VM) ->
send({vm, delete, User, VM}).
delete(VM) ->
delete(undefined, VM).
-spec store(User::fifo:vm_id() | undefined,
VM::fifo:vm_id()) ->
ok | not_found |
{'error', 'no_servers'}.
store(User, VM) when
is_binary(VM) ->
send({vm, store, User, VM}).
store(VM) ->
store(undefined, VM).
%%--------------------------------------------------------------------
%% @doc Changes the owner of a VM.
%% @end
%%--------------------------------------------------------------------
-spec owner(User::fifo:user_id() | undefined,
VM::fifo:vm_id(), Owner::fifo:uuid()) ->
ok | not_found |
{'error', 'no_servers'}.
owner(User, VM, Owner) ->
send({vm, owner, User, VM, Owner}).
owner(VM, Owner) ->
owner(undefined, VM, Owner).
%%--------------------------------------------------------------------
%% @doc Updates a VM by attempting to resize it from package
%% perspective and changing some of the config values.
%% @end
%%--------------------------------------------------------------------
-spec update(User::fifo:user_id() | undefined, VM::fifo:vm_id(),
Package::binary() | undefined,
Config::maps:map()) -> ok | not_found |
{'error', 'no_servers'}.
update(User, VM, Package, Config) when
is_binary(VM),
is_map(Config) ->
send({vm, update, User, VM, Package, Config}).
update(VM, Package, Config) ->
update(undefined, VM, Package, Config).
%%--------------------------------------------------------------------
%% @doc Adds a new interface to a VM.
%% @end
%%--------------------------------------------------------------------
-spec add_nic(VM::fifo:vm_id(),
Network::fifo:network_id()) -> ok | not_found |
{'error', 'no_servers'|
'update_failed'|
'claim_failed'|
'not_stopped'|_Reason}.
add_nic(VM, IPRange) when
is_binary(VM),
is_binary(IPRange) ->
send({vm, nic, add, VM, IPRange}).
%%--------------------------------------------------------------------
%% @doc Remove a interface from a VM.
%% @end
%%--------------------------------------------------------------------
-spec remove_nic(VM::fifo:vm_id(),
Mac::binary()) -> ok | not_found |
{'error', 'no_servers'|
'update_failed'|
'not_found'|
'not_stopped'|_Reason}.
remove_nic(VM, Mac) when
is_binary(VM),
is_binary(Mac) ->
send({vm, nic, remove, VM, Mac}).
%%--------------------------------------------------------------------
%% @doc Sets a NIC as primary interface.
%% @end
%%--------------------------------------------------------------------
-spec primary_nic(VM::fifo:vm_id(),
Mac::binary()) -> ok | not_found |
{'error', 'no_servers'|
'update_failed'|
'not_found'|
'not_stopped'|_Reason}.
primary_nic(VM, Mac) when
is_binary(VM),
is_binary(Mac) ->
send({vm, nic, primary, VM, Mac}).
%%--------------------------------------------------------------------
%% @doc Sets the state of a VM.
%% @end
%%--------------------------------------------------------------------
-spec state(VM::fifo:vm_id(),
State::binary()) ->
ok | not_found |
{'error', 'no_servers'}.
state(VM, State) when
is_binary(VM) ->
send({vm, state, VM, State}).
%%--------------------------------------------------------------------
%% @doc Sets the state of a VM.
%% @end
%%--------------------------------------------------------------------
-spec creating(VM::fifo:vm_id(),
Creating::false | {atom(), tuple()}) ->
ok | not_found |
{'error', 'no_servers'}.
creating(VM, Creating) when Creating == false;
is_tuple(Creating) ->
send({vm, creating, VM, Creating}).
%%--------------------------------------------------------------------
%% @doc Sets a service attribute on the VM object in the database
%% @end
%%--------------------------------------------------------------------
-spec set_service(VM::fifo:vm_id(),
[{Attribute::fifo:keys(),
Value::fifo:value() | delete}]) ->
ok | not_found |
{'error', 'no_servers'}.
set_service(VM, AVs) when
is_binary(VM),
is_list(AVs) ->
send({vm, set_service, VM, AVs}).
%%--------------------------------------------------------------------
%% @doc Sets a backup attribute on the VM object in the database
%% @end
%%--------------------------------------------------------------------
-spec set_backup(VM::fifo:vm_id(),
[{Attribute::fifo:keys(),
Value::fifo:value() | delete}]) ->
ok | not_found |
{'error', 'no_servers'}.
set_backup(VM, AVs) when
is_binary(VM),
is_list(AVs)->
send({vm, set_backup, VM, AVs}).
%%--------------------------------------------------------------------
%% @doc Sets a backup attribute on the VM object in the database
%% @end
%%--------------------------------------------------------------------
-spec set_snapshot(VM::fifo:vm_id(),
[{Attribute::fifo:keys(),
Value::fifo:value() | delete}]) ->
ok | not_found |
{'error', 'no_servers'}.
set_snapshot(VM, AVs) when
is_binary(VM) ->
send({vm, set_snapshot, VM, AVs}).
%%--------------------------------------------------------------------
%% @doc Sets a metadata attribute on the VM object in the database
%% @end
%%--------------------------------------------------------------------
-spec set_metadata(VM::fifo:vm_id(),
[{Attribute::fifo:keys(),
Value::fifo:value() | delete}]) ->
ok | not_found |
{'error', 'no_servers'}.
set_metadata(VM, AVs) when
is_binary(VM),
is_list(AVs) ->
send({vm, set_metadata, VM, AVs}).
%%--------------------------------------------------------------------
%% @doc Sets a config attribute on the VM object in the database
%% @end
%%--------------------------------------------------------------------
-spec set_config(VM::fifo:vm_id(),
[{Attribute::fifo:keys(),
Value::fifo:value() | delete}]) ->
ok | not_found |
{'error', 'no_servers'}.
set_config(VM, AVs) when
is_binary(VM) ->
send({vm, set_config, VM, AVs}).
%%--------------------------------------------------------------------
%% @doc Sets a info attribute on the VM object in the database
%% @end
%%--------------------------------------------------------------------
-spec set_info(VM::fifo:vm_id(),
[{Attribute::fifo:keys(),
Value::fifo:value() | delete}]) ->
ok | not_found |
{'error', 'no_servers'}.
set_info(VM, AVs) when
is_binary(VM),
is_list(AVs) ->
send({vm, set_info, VM, AVs}).
%%--------------------------------------------------------------------
%% @doc Adds a log to the VM that will be timestamped on the server.
%% @end
%%--------------------------------------------------------------------
-spec log(Vm::fifo:uuid(), Log::binary()) -> ok |
{'error', 'no_servers'}.
log(Vm, Log) ->
send({vm, log, Vm, Log}).
%%--------------------------------------------------------------------
%% @doc Creates a full backup of a VM.
%% @end
%%--------------------------------------------------------------------
incremental_backup(Vm, Parent, Comment, Opts) ->
send({vm, backup, incremental, Vm, Parent, Comment, Opts}).
%%--------------------------------------------------------------------
%% @doc Creates a full backup of a VM.
%% @end
%%--------------------------------------------------------------------
full_backup(Vm, Comment, Opts) ->
send({vm, backup, full, Vm, Comment, Opts}).
%%--------------------------------------------------------------------
%% @doc Restores a VM from a backup.
%% @end
%%--------------------------------------------------------------------
restore_backup(Vm, Backup) ->
send({vm, backup, restore, Vm, Backup}).
%%--------------------------------------------------------------------
%% @doc Restores a VM from a backup to a specific hypervisor.
%% @end
%%--------------------------------------------------------------------
restore_backup(Vm, Backup, Hypervisor) ->
restore_backup(undefined, Vm, Backup, Hypervisor).
restore_backup(User, Vm, Backup, Rules) ->
send({vm, backup, restore, User, Vm, Backup, Rules}).
restore_backup(User, Vm, Backup, Package, Rules) ->
send({vm, backup, restore, User, Vm, Backup, Package, Rules}).
%%--------------------------------------------------------------------
%% @doc Deletes the backup of a VM.
%% @end
%%--------------------------------------------------------------------
delete_backup(Vm, Backup, Where) ->
send({vm, backup, delete, Vm, Backup, Where}).
%%--------------------------------------------------------------------
%% @doc Enables a service on a VM.
%% @end
%%--------------------------------------------------------------------
service_enable(Vm, Service) ->
send({vm, service, enable, Vm, Service}).
%%--------------------------------------------------------------------
%% @doc Enables a service on a VM.
%% @end
%%--------------------------------------------------------------------
service_disable(Vm, Service) ->
send({vm, service, disable, Vm, Service}).
%%--------------------------------------------------------------------
%% @doc Enables a service on a VM.
%% @end
%%--------------------------------------------------------------------
service_clear(Vm, Service) ->
send({vm, service, clear, Vm, Service}).
%%--------------------------------------------------------------------
%% @doc Restarts a service on a VM.
%% @end
%%--------------------------------------------------------------------
service_restart(Vm, Service) ->
send({vm, service, restart, Vm, Service}).
%%--------------------------------------------------------------------
%% @doc Refreshes a service on a VM.
%% @end
%%--------------------------------------------------------------------
service_refresh(Vm, Service) ->
send({vm, service, refresh, Vm, Service}).
%%--------------------------------------------------------------------
%% @doc Creates a ZFS new snapshot of a given VM.
%% @end
%%--------------------------------------------------------------------
-spec snapshot(Vm::fifo:uuid(), Comment::binary()) ->
{ok, fifo:uuid()} |
{'error', 'no_servers'}.
snapshot(Vm, Comment) ->
send({vm, snapshot, Vm, Comment}).
%%--------------------------------------------------------------------
%% @doc Deletes a ZFS snapshot from the VM.
%% @end
%%--------------------------------------------------------------------
-spec delete_snapshot(Vm::fifo:uuid(),
UUID::binary()) ->
ok |
{'error', 'no_servers'}.
delete_snapshot(Vm, UUID) ->
send({vm, snapshot, delete, Vm, UUID}).
%%--------------------------------------------------------------------
%% @doc Rolls back a snapshot of a VM, this will <b>delete</b> all
%% snapshots between the current state and the rolled back snapshot!
%% @end
%%--------------------------------------------------------------------
-spec rollback_snapshot(Vm::fifo:uuid(),
UUID::fifo:uuid()) ->
ok |
{'error', 'no_servers'}.
rollback_snapshot(Vm, UUID) ->
send({vm, snapshot, rollback, Vm, UUID}).
%%--------------------------------------------------------------------
%% @doc Confirms the rollback of a snapshot, this will delete all
%% snapshots between the current state and the rolled back snapshot!
%% @end
%%--------------------------------------------------------------------
-spec commit_snapshot_rollback(Vm::fifo:uuid(),
UUID::fifo:uuid()) ->
ok |
{'error', 'no_servers'}.
commit_snapshot_rollback(Vm, UUID) ->
send({vm, snapshot, commit_rollback, Vm, UUID}).
%%--------------------------------------------------------------------
%% @doc Rolls back a snapshot of a VM, this will <b>delete</b> all
%% snapshots between the current state and the rolled back snapshot!
%% @end
%%--------------------------------------------------------------------
-spec promote_snapshot(Vm::fifo:uuid(),
UUID::fifo:uuid(),
Config::fifo:object()) ->
{ok, UUID::fifo:dataset_id()} |
{'error', 'no_servers'}.
promote_snapshot(Vm, UUID, Config) ->
send({vm, snapshot, promote, Vm, UUID, Config}).
%%--------------------------------------------------------------------
%% @doc Lists the UUID's of all VM's known to the server.
%% @end
%%--------------------------------------------------------------------
-spec list() -> {ok, [fifo:uuid()]} |
{'error', 'no_servers'}.
list() ->
send({vm, list}).
%%--------------------------------------------------------------------
%% @doc Lists the UUID's of all VM's known to the server filtered by
%% given matchers.
%% @end
%%--------------------------------------------------------------------
-spec list(Reqs::[fifo:matcher()], boolean()) ->
{ok, [{Ranking::integer(), fifo:vm_id()}]} |
{ok, [{Ranking::integer(), fifo:vm()}]} |
{'error', 'no_servers'}.
list(Reqs, Full) ->
send({vm, list, Reqs, Full}).
%%--------------------------------------------------------------------
%% @doc Streams the VM's in chunks.
%% @end
%%--------------------------------------------------------------------
-spec stream(Reqs::[fifo:matcher()], mdns_client_lib:stream_fun(), term()) ->
{ok, [{Ranking::integer(), fifo:vm_id()}]} |
{ok, [{Ranking::integer(), fifo:vm()}]} |
{'error', 'no_servers'}.
stream(Reqs, StreamFn, Acc0) ->
case libsniffle_server:stream({vm, stream, Reqs}, StreamFn, Acc0) of
{reply, Reply} ->
Reply;
noreply ->
ok;
E ->
E
end.
%%%===================================================================
%%% Internal Functions
%%%===================================================================
-spec send(MSG::fifo:sniffle_vm_message()) ->
ok |
not_found |
atom() |
{ok, Reply::term()} |
{error, no_server} |
{error, Reason::term()}.
send(Msg) ->
send(mdns, Msg).
send(Sniffle, Msg) ->
case libsniffle_server:send(Sniffle, Msg) of
{reply, Reply} ->
Reply;
noreply ->
ok;
E ->
E
end.