Previous Topic: BFC 3.0 and 3.1 - Node Imaging Timeout SettingNext Topic: BFC 3.5: Bare Metal Install with the BMI ISO Tool


gridos_util_30_31

#!/usr/bin/env escript

%% -*- erlang -*-

%%%! -sname gridos_util

%%-------------------------------------------------------

%%

%% Copyright 2010, CA Incorporated. All rights reserved.

%%

%% $Id:$

%%

%%-------------------------------------------------------

-module(gridos_util).

-export([main/1]).

%%

%% Defines

%%

-define(GRIDOS_XEN_RESOURCE_DRIVER, 'core/bbc.gridos_xen.resource.driver').

-define(GRIDOS_ESX_RESOURCE_DRIVER, 'core/bbc.gridos_esx.resource.driver').

-define(GRIDOS_BACKBONE_IP, 'bbc/properties.gridos_backbone_ip').

-define(GRIDOS_VERSION, 'bbc/properties.gridos_version').

-define(GRID_VERSION_RESOURCE, 'bbc/applogic_version_resource').

-define(GRID_VERSION_NAME, 'bbc/properties.grid_version_name').

-define(GRID_VERSION_ESX_ENABLED, 'bbc/properties.grid_version_esx_enabled').

-define(STATE_INFO, 'core/properties.component_state_information').

-define(GRIDOS_XEN_SERVICE_DRIVER, 'core/bbc.gridos_xen.service.driver').

-define(GRIDOS_ESX_SERVICE_DRIVER, 'core/bbc.gridos_esx.service.driver').

-define(GRIDOS_SERVICE_DEPLOYER_TIMEOUT,

'core/gridos.service.deployer.timeout').

-define(GRIDOS_SERVICE_DEPLOYER_RETRIES,

'core/gridos.service.deployer.retries').

list_timeouts() ->

FmtStr = "~-5s ~-20s ~-8s ~-8s~n",

io:format("GridOS Service Timeouts~n~n"),

io:format(FmtStr, ["id", "service", "timeout", "retries"]),

lists:foreach(

fun(GridOSService) ->

[GridOSId] = instances_for_component_type(GridOSService),

%io:format("GridOS ESX Service Timeouts: ~p:~p~n",

% [GridOSService, GridOSId]),

Timeout = property_get(GridOSId, ?GRIDOS_SERVICE_DEPLOYER_TIMEOUT),

Retries = property_get(GridOSId, ?GRIDOS_SERVICE_DEPLOYER_RETRIES),

% io:format(" timeout: ~p~n", [Timeout]),

% io:format(" retries: ~p~n", [Retries]),

io:format(FmtStr, [integer_to_list(GridOSId),

GridOSService,

integer_to_list(Timeout),

integer_to_list(Retries)]),

ok

end,

[?GRIDOS_XEN_SERVICE_DRIVER, ?GRIDOS_ESX_SERVICE_DRIVER]),

ok.

list_versions() ->

FmtStr = "~-5s ~-7s ~-6s ~s~n",

io:format(FmtStr, ["id", "name", "esx", "resource state"]),

lists:foreach(

fun(VersId) ->

io:format(FmtStr, [

integer_to_list(VersId),

property_get(VersId, ?GRID_VERSION_NAME),

property_get(VersId, ?GRID_VERSION_ESX_ENABLED),

get_state(VersId)

])

end,

instances_for_component_type(?GRID_VERSION_RESOURCE)),

ok.

list_gridos_servers() ->

FmtStr = "~-5s ~-5s ~-14s ~-7s ~-25s ~-40s~n",

io:format(FmtStr, ["id", "type", "backbone ip", "version",

"resource state", "info"]),

ESXIds = instances_for_component_type(?GRIDOS_ESX_RESOURCE_DRIVER),

display_each_instance(ESXIds, "esx", FmtStr),

XenIds = instances_for_component_type(?GRIDOS_XEN_RESOURCE_DRIVER),

display_each_instance(XenIds, "xen", FmtStr),

ok.

display_each_instance([], _Type, _FmtStr) ->

ok;

display_each_instance([Id|Tail], Type, FmtStr)->

IP = property:array_get(1, property_get(Id, ?GRIDOS_BACKBONE_IP)),

io:format(FmtStr, [integer_to_list(Id), Type, IP,

property_get(Id, ?GRIDOS_VERSION), get_state(Id),

get_state_info_msg(Id)]),

display_each_instance(Tail, Type, FmtStr).

update_timeoutes(Options) ->

GridOSServiceId = orddict:fetch(gridosserviceid, Options),

TimeoutValue = orddict:fetch(timeoutvalue, Options),

RetriesValue = orddict:fetch(retriesvalue, Options),

update_timeouts(GridOSServiceId, TimeoutValue, RetriesValue),

ok.

update_timeouts(Id, undefined, undefined) ->

io:format("Undefined,Undefined~n"),

throw({badarg, "GridOS Service Id specified without either a "

"Timeout or a Retries value",

{id, Id}});

update_timeouts(Id, Timeout, undefined) ->

property_set(Id, ?GRIDOS_SERVICE_DEPLOYER_TIMEOUT, Timeout);

update_timeouts(Id, undefined, Retries) ->

property_set(Id, ?GRIDOS_SERVICE_DEPLOYER_RETRIES, Retries);

update_timeouts(Id, Timeout, Retries) ->

property_set(Id, ?GRIDOS_SERVICE_DEPLOYER_TIMEOUT, Timeout),

property_set(Id, ?GRIDOS_SERVICE_DEPLOYER_RETRIES, Retries).

release(Options) ->

ComponentId = orddict:fetch(id, Options),

io:format("Releasing component: ~b~n", [ComponentId]),

% validate it is a existing component id

CurState = get_state(ComponentId),

case CurState of

{badrpc, Error} ->

io:format("Error: component id not valid: ~n~p~n", [Error]),

throw({release_failed, Error});

_ ->

ok

end,

% release it

Result = rpc:call(get(nodename), find, release, [ComponentId]),

io:format("release result: ~p~n", [Result]),

ok.

send_event(Options) ->

CompId = orddict:fetch(id, Options),

EventName = case orddict:fetch(eventname, Options) of

undefined ->

io:format("Error: --send-event=<id> requires "

"the --event=<event_name> option~n"),

throw({no_event_name});

Name -> list_to_atom(Name)

end,

Result = component_send_event(CompId, EventName),

io:format("Sending event ~p to component ~p -> Result: ~p~n",

[EventName, CompId, Result]),

ok.

allocate_esx(Options) ->

LicenseKey = case orddict:fetch(licensekey, Options) of

undefined ->

io:format("Error: ESX GridOS servers require a "

"<licenseKey>~n"),

throw({no_license_key});

Key -> Key

end,

allocate_gridos(Options, ?GRIDOS_ESX_RESOURCE_DRIVER, LicenseKey).

allocate_xen(Options) ->

allocate_gridos(Options, ?GRIDOS_XEN_RESOURCE_DRIVER, "undefined").

allocate_gridos(Options, Type, LicenseKey) ->

GridOSId = rpc:call(get(nodename), find, find_confirmed, [Type]),

case GridOSId of

none ->

io:format("Error: allocation failed.~n"),

throw({allocation_failed});

_ ->

io:format("[id:~p] AllocateGridOS complete~n", [GridOSId])

end,

component_call(GridOSId, setGridVersion, [orddict:fetch(versid, Options)]),

component_call(GridOSId, setLicenseKey, [LicenseKey]),

component_send_event(GridOSId, resource_start_event),

io:format("[id:~p] resource_start_event sent, "

"polling for running state...~n", [GridOSId]),

wait_for_running_or_failed(GridOSId, get_state(GridOSId), "GridOS"),

component_call(GridOSId, setInGrid, [true]),

ok.

get_state_info_msg(Id) ->

StateInfo = property_get(Id, ?STATE_INFO),

case property_get(Id, ?STATE_INFO) of

none -> "";

StateInfo -> orddict:fetch(<<"fmt">>, StateInfo)

end.

wait_for_running_or_failed(Id, resource_running_state, ResourceName) ->

io:format("~s:~p has reached the Running state~n", [ResourceName, Id]),

ok;

wait_for_running_or_failed(Id, resource_failed_state, ResourceName) ->

io:format("Error: ~s:~p has reached the Failed state, info: ~s~n",

[ResourceName, Id, get_state_info_msg(Id)]),

throw({gridos_failed_node, Id});

wait_for_running_or_failed(Id, State, ResourceName) ->

io:format("[id:~p][~s] -> ~-28s:~-45s~n",

[Id, time_stamp(), State, get_state_info_msg(Id)]),

timer:sleep(30*1000), % pause 30 seconds

wait_for_running_or_failed(Id, get_state(Id), ResourceName).

activate_esx(Options) ->

VersId = orddict:fetch(versid, Options),

EsxCD = case orddict:fetch(esxCD, Options) of

undefined ->

io:format("Error: --esx-cd <...> not specified, required "

"for --activate-esx~n"),

throw({activate_esx_failed});

E -> E

end,

verboseMsg("activate_esx(vers=~b, esxcd=~s)~n", [VersId, EsxCD], Options),

Res = component_call(VersId, importEsxVersion, [EsxCD]),

verboseMsg("result: ~p~n", [Res], Options).

upgrade_gridos(Options) ->

GridOSID = orddict:fetch(id, Options),

VersId = case orddict:fetch(upgradeVers, Options) of

undefined ->

io:format("Error: --upgrade-vers <versid> not specified, required "

"for --upgrade...~n"),

throw(upgrade_failed);

VId -> VId

end,

io:format("Upgrading Gridos:~b -> ~b~n", [GridOSID, VersId]),

Res = component_call(GridOSID, upgrade, [VersId]),

verboseMsg("result: ~p~n", [Res], Options).

import_version(Options) ->

VersId = orddict:fetch(versid, Options),

component_send_event(VersId, resource_start_event),

io:format("[id:~p] resource_start_event sent, "

"polling for running state...~n", [VersId]),

wait_for_running_or_failed(VersId, get_state(VersId), "Version").

time_stamp() ->

{H, M, S} = time(),

io_lib:format("~2.10.0b:~2.10.0b:~2.10.0b", [H, M, S]).

%%

%% BFC Access

%%

property_get(Id, Name) ->

case rpc:call(get(nodename), property, get, [Id, Name]) of

{value, Value} -> Value;

none -> none

end.

property_set(Id, Name, Value) ->

rpc:call(get(nodename), property, set, [Id, Name, Value]).

get_state(Id) ->

rpc:call(get(nodename), component, get_state, [Id]).

instances_for_component_type(Type) ->

rpc:call(get(nodename), component_impl, instances_for_component_type,

[Type]).

component_call(Id, Op, Args) ->

rpc:call(get(nodename), component, call, [Id, Op, Args]).

component_send_event(Id, Event) ->

rpc:call(get(nodename), component, send_event, [Id, Event]).

%%

%% Options Parsing

%%

parse_opts(Args) ->

Options = orddict:from_list([

{verbose, false},

{help, false},

{allocateXen, false},

{allocateESX, false},

{versid, undefiend},

{release, false},

{licensekey, undefined},

{importVersion, false},

{activateEsx, false},

{esxCD, undefined},

{upgrade, false},

{upgradeVers, undefined},

{listgridos, false},

{listversions, false},

{sendevent, false},

{eventname, undefined},

{listtimeouts, false},

{gridosserviceid, undefined},

{timeoutvalue, undefined},

{retriesvalue, undefined}

]),

parse_opts(Args, Options).

parse_opts(["-h"|Tail], Options) ->

parse_opts(Tail, orddict:store(help, true, Options));

parse_opts(["--help"|Tail], Options) ->

parse_opts(Tail, orddict:store(help, true, Options));

parse_opts(["--verbose"|Tail], Options) ->

parse_opts(Tail, orddict:store(verbose, true, Options));

parse_opts(["--list-gridos"|Tail], Options) ->

parse_opts(Tail, orddict:store(listgridos, true, Options));

parse_opts(["--list-versions"|Tail], Options) ->

parse_opts(Tail, orddict:store(listversions, true, Options));

parse_opts(["--license-key=" ++ LicKey|Tail], Options) ->

parse_opts(Tail,

parse_str_arg(LicKey, licensekey, "--license-key", Options));

parse_opts(["--import-version=" ++ Id|Tail], Options) ->

parse_opts(Tail,

parse_int_arg(Id, versid, "--import-version",

orddict:store(importVersion, true, Options)));

parse_opts(["--activate-esx=" ++ Id|Tail], Options) ->

parse_opts(Tail,

parse_int_arg(Id, versid, "--activate-esx",

orddict:store(activateEsx, true, Options)));

parse_opts(["--esx-cd=" ++ EsxCd|Tail], Options) ->

parse_opts(Tail, parse_str_arg(EsxCd, esxCD, "--esx-cd=", Options));

parse_opts(["--allocate-xen=" ++ Id|Tail], Options) ->

parse_opts(Tail,

parse_int_arg(Id, versid, "--allocate-xen=",

orddict:store(allocateXen, true, Options)));

parse_opts(["--allocate-esx=" ++ Id|Tail], Options) ->

parse_opts(Tail,

parse_int_arg(Id, versid, "--allocate-esx=",

orddict:store(allocateESX, true, Options)));

parse_opts(["--upgrade=" ++ Id|Tail], Options) ->

parse_opts(Tail,

parse_int_arg(Id, id, "--upgrade",

orddict:store(upgrade, true, Options)));

parse_opts(["--upgrade-vers=" ++ Id|Tail], Options) ->

parse_opts(Tail,

parse_int_arg(Id, 'upgradeVers', "--upgrade-vers=", Options));

parse_opts(["--release=" ++ Id|Tail], Options) ->

parse_opts(Tail,

parse_int_arg(Id, id, "--release=",

orddict:store(release, true, Options)));

parse_opts(["--send-event=" ++ Id|Tail], Options) ->

parse_opts(Tail,

parse_int_arg(Id, id, "--send-event=",

orddict:store(sendevent, true, Options)));

parse_opts(["--event=" ++ EventName|Tail], Options) ->

parse_opts(Tail,

parse_str_arg(EventName, eventname, "--event=", Options));

parse_opts(["--list-timeouts"|Tail], Options) ->

parse_opts(Tail, orddict:store(listtimeouts, true, Options));

parse_opts(["--gridos-service-id=" ++ Id | Tail], Options) ->

parse_opts(Tail,

parse_int_arg(Id, gridosserviceid, "--grid-service-id=",

Options));

parse_opts(["--set-timeout=" ++ Val | Tail], Options) ->

parse_opts(Tail,

parse_int_arg(Val, timeoutvalue, "--set-timeout=", Options));

parse_opts(["--set-retries=" ++ Val | Tail], Options) ->

parse_opts(Tail,

parse_int_arg(Val, retriesvalue, "--set-retries=", Options));

parse_opts([BadOpt| _Tail], _Options) ->

io:format("Error: unexpected option: ~s~n", [BadOpt]),

usage(),

throw({badoption, BadOpt});

parse_opts([], Options) ->

Options.

parse_str_arg(Str, OptKey, OptTag, Options) ->

case Str of

[] ->

io:format("Error: no ~s spefieid for ~s~n", [OptKey, OptTag]),

throw({badoptions, missing_arg});

_ -> orddict:store(OptKey, Str, Options)

end.

parse_int_arg(IntStr, OptKey, OptTag, Options) ->

case string:to_integer(IntStr) of

{error, _} ->

io:format("Error: bad ~s listed for ~s~n", [OptKey, OptTag]),

usage(),

throw({badoption, bad_versid});

{Int, _Rest} ->

orddict:store(OptKey, Int, Options)

end;

parse_int_arg([], OptKey, OptTag, _Options) ->

io:format("Error: no ~s listed for ~s~n", [OptKey, OptTag]),

usage(),

throw({badoption, no_versid}).

help() ->

usage(),

halt(1).

usage() ->

io:format(

"Usage: gridos_util [Options]~n"

" --help~n"

" This usage message~n"

" --list-gridos~n"

" List all GridOs Resources~n"

" --list-versions~n"

" List all Versions~n"

" --import-version=<versId>~n"

" Import a specific version, driving it to the running~n"

" state.~n"

" --activate-esx=<versId>~n"

" Activate ESX for a specific <versId>, you must~n"

" also specify the --esx-cd ... option when~n"

" doing this~n"

" --esx-cd=<pathToEsxCdimage>~n"

" Path to ESX Install CD, to be used with~n"

" --activate-esx...~n"

" --allocate-xen=<versId>~n"

" Allocate a Xen based GridOS resource and drive it to~n"

" the running state. The version to be installed is~n"

" <versId>~n"

" --allocate-esx=<versId>~n"

" Allocate a ESX based GridOS resource and drive it to~n"

" the running state. The version to be installed is~n"

" <versid>. ESX also requires that you specify~n"

" a <licenseKey>~n"

" --license-key=<LicenseKey>~n"

" A license key to be given to a GridOS resource durring~n"

" allocation.~n"

" --upgrade=<id>~n"

" Upgrade a GridOS resource <id> to a new version,~n"

" The new version is identified by --upgrade-vers=<id>~n"

" --upgrade-vers=<versid>~n"

" New version to upgrade to~n"

" --release=<id>~n"

" Release the specified component and its~n"

" assocaited hardware~n"

" --send-event=<id>~n"

" Send a event to the component <id>. The event~n"

" sent is identified by the --event=<event_name>~n"

" arguement, this option is required.~n"

" --event=<event_name>~n"

" Name of event to be sent.~n"

" --list-timeouts~n"

" List ESX and Xen GridOS timeouts and retry counts~n"

" --gridos-service-id=<id>~n"

" ID of GridOS Service to be updates, see set-timeout~n"

" and set-retries~n"

" --set-timeout=<value>~n"

" Set timeout of GridOS Service to <value>~n"

" --set-retries=<value>~n"

" Set retries of GridOS Service to <value>~n"

).

verboseMsg(FmtStr, Args, Options) ->

Verbose = orddict:fetch(verbose, Options),

if

Verbose -> io:format(FmtStr, Args);

true -> ok

end.

set_node_name(Options) ->

{N1, N2, N3} = now(),

MyNode = "gridos_util" ++ integer_to_list(N1) ++

integer_to_list(N2) ++ integer_to_list(N3),

verboseMsg("NodeName: ~s~n", [MyNode], Options),

net_kernel:start([list_to_atom(MyNode), shortnames]).

%%

%% Main

%%

main(Args) ->

Options = try parse_opts(Args)

catch throw:_ -> halt(1)

end,

verboseMsg("Options: ~p~n", [Options], Options),

set_node_name(Options),

NodeName = list_to_atom("bfc@" ++

string:strip(os:cmd("hostname -s"), right, $\n)),

put(nodename, NodeName),

HelpOption = orddict:fetch(help, Options),

ListGridOS = orddict:fetch(listgridos, Options),

ListVersions = orddict:fetch(listversions, Options),

AllocateXen = orddict:fetch(allocateXen, Options),

AllocateESX = orddict:fetch(allocateESX, Options),

Release = orddict:fetch(release, Options),

ImportVersion = orddict:fetch(importVersion, Options),

ActivateEsx = orddict:fetch(activateEsx, Options),

Upgrade = orddict:fetch(upgrade, Options),

SendEvent = orddict:fetch(sendevent, Options),

ListTimeouts = orddict:fetch(listtimeouts, Options),

UpdateTimeouts =

case orddict:fetch(gridosserviceid, Options) of

undefined -> false;

_ -> true

end,

try

if

HelpOption -> help();

ListGridOS -> list_gridos_servers();

ListVersions -> list_versions();

ListTimeouts -> list_timeouts();

Release -> release(Options);

AllocateXen -> allocate_xen(Options);

AllocateESX -> allocate_esx(Options);

ImportVersion -> import_version(Options);

ActivateEsx -> activate_esx(Options);

Upgrade -> upgrade_gridos(Options);

SendEvent -> send_event(Options);

UpdateTimeouts -> update_timeoutes(Options);

true ->

io:format("Error: no options specified~n"),

usage()

end

catch throw:Msg ->

io:format("Failure Thrown: ~p~n", [Msg]),

halt(1)

end,

halt(0).