Removed all projects except Glazier Deployment
This commit is contained in:
parent
c3083f5f6a
commit
0f5debdcb1
|
@ -1,17 +0,0 @@
|
|||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Rr]elease/
|
||||
x64/
|
||||
build/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
</startup>
|
||||
</configuration>
|
|
@ -1,62 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{501BE151-4B8C-4355-88DC-3AEF1921B2D7}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>ConsoleApplication1</RootNamespace>
|
||||
<AssemblyName>ExecutionPlanGenerator</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
|
@ -1,141 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ConsoleApplication1
|
||||
{
|
||||
class Command
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public Dictionary<string, object> Arguments { get; set; }
|
||||
}
|
||||
class ExecutionPlan
|
||||
{
|
||||
public List<string> Scripts { get; set; }
|
||||
public List<Command> Commands { get; set; }
|
||||
public int RebootOnCompletion { get; set; }
|
||||
}
|
||||
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
if (args.Length < 1 || args.Length > 2)
|
||||
{
|
||||
Console.WriteLine("Usage: ExecutionPlanGenerator inputfile [outputfile]");
|
||||
return;
|
||||
}
|
||||
|
||||
var outFile = args.Length == 2 ? args[1] : null;
|
||||
|
||||
var plan = new ExecutionPlan {
|
||||
Scripts = new List<string>(),
|
||||
Commands = new List<Command>()
|
||||
};
|
||||
|
||||
|
||||
|
||||
var lines = File.ReadAllLines(args[0]);
|
||||
|
||||
|
||||
foreach (var statement in lines
|
||||
.Select(t => t.Split(new[] { ' ', '\t' }, 2))
|
||||
.Where(t => t.Length == 2)
|
||||
.Select(t => new Tuple<string, string>(t[0].Trim().ToLower(), t[1].Trim())))
|
||||
{
|
||||
switch (statement.Item1)
|
||||
{
|
||||
case "include":
|
||||
Include(statement.Item2, plan, args[0]);
|
||||
break;
|
||||
case "call":
|
||||
Call(statement.Item2, plan);
|
||||
break;
|
||||
case "reboot":
|
||||
plan.RebootOnCompletion = int.Parse(statement.Item2);
|
||||
break;
|
||||
case "out":
|
||||
if (args.Length < 2)
|
||||
{
|
||||
var path = statement.Item2;
|
||||
if (!Path.IsPathRooted(path))
|
||||
{
|
||||
path = Path.Combine(Path.GetDirectoryName(args[0]), path);
|
||||
}
|
||||
outFile = path;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var data = JsonConvert.SerializeObject(plan, Formatting.Indented);
|
||||
if (outFile == null)
|
||||
{
|
||||
Console.WriteLine(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
File.WriteAllText(outFile, data);
|
||||
}
|
||||
}
|
||||
|
||||
private static void Call(string line, ExecutionPlan plan)
|
||||
{
|
||||
var parts = line.Split(new[] { ' ', '\t'}, 2);
|
||||
var command = new Command() {
|
||||
Name = parts[0].Trim(),
|
||||
Arguments = new Dictionary<string, object>()
|
||||
};
|
||||
|
||||
|
||||
if (parts.Length == 2)
|
||||
{
|
||||
foreach (var x in parts[1]
|
||||
.Split(',')
|
||||
.Select(t => t.Split('='))
|
||||
.Where(t => t.Length == 2)
|
||||
.Select(t => new KeyValuePair<string, string>(t[0].Trim(), t[1].Trim())))
|
||||
{
|
||||
object value = null;
|
||||
long num;
|
||||
bool boolean;
|
||||
if (x.Value.StartsWith("\""))
|
||||
{
|
||||
value = x.Value.Substring(1, x.Value.Length - 2);
|
||||
}
|
||||
else if (long.TryParse(x.Value, out num))
|
||||
{
|
||||
value = num;
|
||||
}
|
||||
else if (bool.TryParse(x.Value, out boolean))
|
||||
{
|
||||
value = boolean;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
command.Arguments.Add(x.Key, value);
|
||||
}
|
||||
}
|
||||
plan.Commands.Add(command);
|
||||
}
|
||||
|
||||
private static void Include(string file, ExecutionPlan plan, string dslPath)
|
||||
{
|
||||
var path = file;
|
||||
if (!Path.IsPathRooted(file))
|
||||
{
|
||||
path = Path.Combine(Path.GetDirectoryName(dslPath), path);
|
||||
}
|
||||
|
||||
var text = File.ReadAllText(path, Encoding.UTF8);
|
||||
plan.Scripts.Add(Convert.ToBase64String(Encoding.UTF8.GetBytes(text)));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("ConsoleApplication1")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("ConsoleApplication1")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2013")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("9aab688a-ce5f-402e-8891-2d7b4ae85ea3")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -1,4 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="4.5.11" targetFramework="net45" />
|
||||
</packages>
|
Binary file not shown.
|
@ -1,26 +0,0 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2012
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsAgent", "WindowsAgent\WindowsAgent.csproj", "{F7E2A8D5-6D24-4651-A4BC-1024D59F4903}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExecutionPlanGenerator", "ExecutionPlanGenerator\ExecutionPlanGenerator.csproj", "{501BE151-4B8C-4355-88DC-3AEF1921B2D7}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{F7E2A8D5-6D24-4651-A4BC-1024D59F4903}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F7E2A8D5-6D24-4651-A4BC-1024D59F4903}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F7E2A8D5-6D24-4651-A4BC-1024D59F4903}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F7E2A8D5-6D24-4651-A4BC-1024D59F4903}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{501BE151-4B8C-4355-88DC-3AEF1921B2D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{501BE151-4B8C-4355-88DC-3AEF1921B2D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{501BE151-4B8C-4355-88DC-3AEF1921B2D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{501BE151-4B8C-4355-88DC-3AEF1921B2D7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -1,30 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog"/>
|
||||
</configSections>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
</startup>
|
||||
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<targets>
|
||||
<target name="file" xsi:type="File" fileName="${basedir}/log.txt"
|
||||
layout="${date} ${level}: <${logger:shortName=true}> ${message} ${exception:format=tostring}"/>
|
||||
</targets>
|
||||
|
||||
<rules>
|
||||
<logger name="*" minlevel="Debug" writeTo="file" />
|
||||
</rules>
|
||||
</nlog>
|
||||
<appSettings>
|
||||
<add key="rabbitmq.host" value="localhost"/>
|
||||
<add key="rabbitmq.user" value="keero"/>
|
||||
<add key="rabbitmq.password" value="keero"/>
|
||||
<add key="rabbitmq.vhost" value="keero"/>
|
||||
<add key="rabbitmq.resultExchange" value=""/>
|
||||
<add key="rabbitmq.resultRoutingKey" value="-execution-results"/>
|
||||
<add key="rabbitmq.durableMessages" value="true"/>
|
||||
|
||||
</appSettings>
|
||||
</configuration>
|
|
@ -1,21 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Mirantis.Keero.WindowsAgent
|
||||
{
|
||||
class ExecutionPlan
|
||||
{
|
||||
public class Command
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public Dictionary<string, object> Arguments { get; set; }
|
||||
}
|
||||
|
||||
public string[] Scripts { get; set; }
|
||||
public LinkedList<Command> Commands { get; set; }
|
||||
public int RebootOnCompletion { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Mirantis.Keero.WindowsAgent
|
||||
{
|
||||
class MqMessage
|
||||
{
|
||||
private readonly Action ackFunc;
|
||||
|
||||
public MqMessage(Action ackFunc)
|
||||
{
|
||||
this.ackFunc = ackFunc;
|
||||
}
|
||||
|
||||
public MqMessage()
|
||||
{
|
||||
}
|
||||
|
||||
public string Body { get; set; }
|
||||
public string Id { get; set; }
|
||||
|
||||
public void Ack()
|
||||
{
|
||||
ackFunc();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,176 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Management.Automation;
|
||||
using System.Management.Automation.Runspaces;
|
||||
using System.Text;
|
||||
using NLog;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Mirantis.Keero.WindowsAgent
|
||||
{
|
||||
class PlanExecutor
|
||||
{
|
||||
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
class ExecutionResult
|
||||
{
|
||||
public bool IsException { get; set; }
|
||||
public object Result { get; set; }
|
||||
}
|
||||
|
||||
private readonly string path;
|
||||
|
||||
public PlanExecutor(string path)
|
||||
{
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public bool RebootNeeded { get; set; }
|
||||
|
||||
public void Execute()
|
||||
{
|
||||
RebootNeeded = false;
|
||||
var resultPath = this.path + ".result";
|
||||
Runspace runSpace = null;
|
||||
try
|
||||
{
|
||||
var plan = JsonConvert.DeserializeObject<ExecutionPlan>(File.ReadAllText(this.path));
|
||||
List<ExecutionResult> currentResults = null;
|
||||
try
|
||||
{
|
||||
currentResults = JsonConvert.DeserializeObject<List<ExecutionResult>>(File.ReadAllText(resultPath));
|
||||
}
|
||||
catch
|
||||
{
|
||||
currentResults = new List<ExecutionResult>();
|
||||
}
|
||||
|
||||
|
||||
runSpace = RunspaceFactory.CreateRunspace();
|
||||
runSpace.Open();
|
||||
|
||||
var runSpaceInvoker = new RunspaceInvoke(runSpace);
|
||||
runSpaceInvoker.Invoke("Set-ExecutionPolicy Unrestricted");
|
||||
if (plan.Scripts != null)
|
||||
{
|
||||
foreach (var script in plan.Scripts)
|
||||
{
|
||||
runSpaceInvoker.Invoke(Encoding.UTF8.GetString(Convert.FromBase64String(script)));
|
||||
}
|
||||
}
|
||||
|
||||
while (plan.Commands != null && plan.Commands.Any())
|
||||
{
|
||||
var command = plan.Commands.First();
|
||||
|
||||
var pipeline = runSpace.CreatePipeline();
|
||||
var psCommand = new Command(command.Name);
|
||||
if (command.Arguments != null)
|
||||
{
|
||||
foreach (var kvp in command.Arguments)
|
||||
{
|
||||
psCommand.Parameters.Add(kvp.Key, kvp.Value);
|
||||
}
|
||||
}
|
||||
|
||||
Log.Info("Executing {0} {1}", command.Name, string.Join(" ",
|
||||
(command.Arguments ?? new Dictionary<string, object>()).Select(
|
||||
t => string.Format("{0}={1}", t.Key, t.Value == null ? "null" : t.Value.ToString()))));
|
||||
|
||||
pipeline.Commands.Add(psCommand);
|
||||
try
|
||||
{
|
||||
var result = pipeline.Invoke();
|
||||
if (result != null)
|
||||
{
|
||||
currentResults.Add(new ExecutionResult {
|
||||
IsException = false,
|
||||
Result = result.Select(SerializePsObject).Where(obj => obj != null).ToList()
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
currentResults.Add(new ExecutionResult {
|
||||
IsException = true,
|
||||
Result = new[] {
|
||||
exception.GetType().FullName, exception.Message
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
finally
|
||||
{
|
||||
plan.Commands.RemoveFirst();
|
||||
File.WriteAllText(path, JsonConvert.SerializeObject(plan));
|
||||
File.WriteAllText(resultPath, JsonConvert.SerializeObject(currentResults));
|
||||
}
|
||||
}
|
||||
runSpace.Close();
|
||||
var executionResult = JsonConvert.SerializeObject(new ExecutionResult {
|
||||
IsException = false,
|
||||
Result = currentResults
|
||||
}, Formatting.Indented);
|
||||
|
||||
if (plan.RebootOnCompletion > 0)
|
||||
{
|
||||
if (plan.RebootOnCompletion == 1)
|
||||
{
|
||||
RebootNeeded = !currentResults.Any(t => t.IsException);
|
||||
}
|
||||
else
|
||||
{
|
||||
RebootNeeded = true;
|
||||
}
|
||||
}
|
||||
File.WriteAllText(resultPath, executionResult);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
File.WriteAllText(resultPath, JsonConvert.SerializeObject(new ExecutionResult {
|
||||
IsException = true,
|
||||
Result = ex.Message
|
||||
}, Formatting.Indented));
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (runSpace != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
runSpace.Close();
|
||||
}
|
||||
catch
|
||||
{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static object SerializePsObject(PSObject obj)
|
||||
{
|
||||
if (obj.BaseObject is PSCustomObject)
|
||||
{
|
||||
var result = new Dictionary<string, object>();
|
||||
foreach (var property in obj.Properties.Where(p => p.IsGettable))
|
||||
{
|
||||
try
|
||||
{
|
||||
result[property.Name] = property.Value.ToString();
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return obj.BaseObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,168 +0,0 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Management.Automation;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using NLog;
|
||||
|
||||
namespace Mirantis.Keero.WindowsAgent
|
||||
{
|
||||
[DisplayName("Keero Agent")]
|
||||
sealed public class Program : WindowsService
|
||||
{
|
||||
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
||||
private volatile bool stop;
|
||||
private Thread thread;
|
||||
private RabbitMqClient rabbitMqClient;
|
||||
private int delayFactor = 1;
|
||||
private string plansDir;
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Start(new Program(), args);
|
||||
}
|
||||
|
||||
protected override void OnStart(string[] args)
|
||||
{
|
||||
base.OnStart(args);
|
||||
|
||||
Log.Info("Version 0.3");
|
||||
|
||||
this.rabbitMqClient = new RabbitMqClient();
|
||||
|
||||
var basePath = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
|
||||
this.plansDir = Path.Combine(basePath, "plans");
|
||||
|
||||
|
||||
if (!Directory.Exists(plansDir))
|
||||
{
|
||||
Directory.CreateDirectory(plansDir);
|
||||
}
|
||||
|
||||
this.thread = new Thread(Loop);
|
||||
this.thread.Start();
|
||||
}
|
||||
|
||||
void Loop()
|
||||
{
|
||||
const string unknownName = "unknown";
|
||||
while (!stop)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var file in Directory.GetFiles(this.plansDir, "*.json.result")
|
||||
.Where(file => !File.Exists(Path.Combine(this.plansDir, Path.GetFileNameWithoutExtension(file)))))
|
||||
{
|
||||
var id = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(file)) ?? unknownName;
|
||||
if (id.Equals(unknownName, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
id = "";
|
||||
}
|
||||
|
||||
var result = File.ReadAllText(file);
|
||||
Log.Info("Sending results for {0}", id ?? unknownName);
|
||||
rabbitMqClient.SendResult(new MqMessage { Body = result, Id = id });
|
||||
File.Delete(file);
|
||||
}
|
||||
|
||||
var path = Directory.EnumerateFiles(this.plansDir, "*.json").FirstOrDefault();
|
||||
if (path == null)
|
||||
{
|
||||
var message = rabbitMqClient.GetMessage();
|
||||
var id = message.Id;
|
||||
if(string.IsNullOrEmpty(id))
|
||||
{
|
||||
id = unknownName;
|
||||
}
|
||||
|
||||
path = Path.Combine(this.plansDir, string.Format("{0}.json", id));
|
||||
File.WriteAllText(path, message.Body);
|
||||
Log.Info("Received new execution plan {0}", id);
|
||||
message.Ack();
|
||||
}
|
||||
else
|
||||
{
|
||||
var id = Path.GetFileNameWithoutExtension(path);
|
||||
Log.Info("Executing exising plan {0}", id);
|
||||
}
|
||||
var executor = new PlanExecutor(path);
|
||||
executor.Execute();
|
||||
File.Delete(path);
|
||||
delayFactor = 1;
|
||||
|
||||
if (stop) break;
|
||||
if (executor.RebootNeeded)
|
||||
{
|
||||
Reboot();
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
WaitOnException(exception);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void Reboot()
|
||||
{
|
||||
Log.Info("Going for reboot!!");
|
||||
LogManager.Flush();
|
||||
/*try
|
||||
{
|
||||
System.Diagnostics.Process.Start("shutdown.exe", "-r -t 0");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.ErrorException("Cannot execute shutdown.exe", ex);
|
||||
}*/
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
PowerShell.Create().AddCommand("Restart-Computer").AddParameter("Force").Invoke();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
|
||||
Log.FatalException("Reboot exception", exception);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Log.Info("Waiting for reboot");
|
||||
for (var i = 0; i < 10 * 60 * 5 && !stop; i++)
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
Log.Info("Done waiting for reboot");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void WaitOnException(Exception exception)
|
||||
{
|
||||
if (stop) return;
|
||||
Log.WarnException("Exception in main loop", exception);
|
||||
var i = 0;
|
||||
while (!stop && i < 10 * (delayFactor * delayFactor))
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
i++;
|
||||
}
|
||||
delayFactor = Math.Min(delayFactor + 1, 6);
|
||||
}
|
||||
|
||||
protected override void OnStop()
|
||||
{
|
||||
stop = true;
|
||||
this.rabbitMqClient.Dispose();
|
||||
base.OnStop();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("WindowsAgent")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("WindowsAgent")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2013")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("9591bf2c-f38b-47e0-a39d-ea9849356371")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -1,128 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NLog;
|
||||
using RabbitMQ.Client;
|
||||
|
||||
namespace Mirantis.Keero.WindowsAgent
|
||||
{
|
||||
class RabbitMqClient : IDisposable
|
||||
{
|
||||
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
||||
private static readonly ConnectionFactory connectionFactory;
|
||||
private IConnection currentConnecton;
|
||||
|
||||
static RabbitMqClient()
|
||||
{
|
||||
connectionFactory = new ConnectionFactory {
|
||||
HostName = ConfigurationManager.AppSettings["rabbitmq.host"] ?? "localhost",
|
||||
UserName = ConfigurationManager.AppSettings["rabbitmq.user"] ?? "guest",
|
||||
Password = ConfigurationManager.AppSettings["rabbitmq.password"] ??"guest",
|
||||
Protocol = Protocols.FromEnvironment(),
|
||||
VirtualHost = ConfigurationManager.AppSettings["rabbitmq.vhost"] ?? "/",
|
||||
RequestedHeartbeat = 10
|
||||
};
|
||||
}
|
||||
|
||||
public RabbitMqClient()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public MqMessage GetMessage()
|
||||
{
|
||||
var queueName = ConfigurationManager.AppSettings["rabbitmq.inputQueue"] ?? Dns.GetHostName().ToLower();
|
||||
try
|
||||
{
|
||||
IConnection connection = null;
|
||||
lock (this)
|
||||
{
|
||||
connection = this.currentConnecton = this.currentConnecton ?? connectionFactory.CreateConnection();
|
||||
}
|
||||
var session = connection.CreateModel();
|
||||
session.BasicQos(0, 1, false);
|
||||
//session.QueueDeclare(queueName, true, false, false, null);
|
||||
var consumer = new QueueingBasicConsumer(session);
|
||||
var consumeTag = session.BasicConsume(queueName, false, consumer);
|
||||
var e = (RabbitMQ.Client.Events.BasicDeliverEventArgs) consumer.Queue.Dequeue();
|
||||
Action ackFunc = delegate {
|
||||
session.BasicAck(e.DeliveryTag, false);
|
||||
session.BasicCancel(consumeTag);
|
||||
session.Close();
|
||||
};
|
||||
|
||||
return new MqMessage(ackFunc) {
|
||||
Body = Encoding.UTF8.GetString(e.Body),
|
||||
Id = e.BasicProperties.MessageId
|
||||
};
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
|
||||
Dispose();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public void SendResult(MqMessage message)
|
||||
{
|
||||
var exchangeName = ConfigurationManager.AppSettings["rabbitmq.resultExchange"] ?? "";
|
||||
var resultRoutingKey = ConfigurationManager.AppSettings["rabbitmq.resultRoutingKey"] ?? "-execution-results";
|
||||
bool durable = bool.Parse(ConfigurationManager.AppSettings["rabbitmq.durableMessages"] ?? "true");
|
||||
|
||||
try
|
||||
{
|
||||
IConnection connection = null;
|
||||
lock (this)
|
||||
{
|
||||
connection = this.currentConnecton = this.currentConnecton ?? connectionFactory.CreateConnection();
|
||||
}
|
||||
var session = connection.CreateModel();
|
||||
/*if (!string.IsNullOrEmpty(resultQueue))
|
||||
{
|
||||
//session.QueueDeclare(resultQueue, true, false, false, null);
|
||||
if (!string.IsNullOrEmpty(exchangeName))
|
||||
{
|
||||
session.ExchangeBind(exchangeName, resultQueue, resultQueue);
|
||||
}
|
||||
}*/
|
||||
var basicProperties = session.CreateBasicProperties();
|
||||
basicProperties.SetPersistent(durable);
|
||||
basicProperties.MessageId = message.Id;
|
||||
basicProperties.ContentType = "application/json";
|
||||
session.BasicPublish(exchangeName, resultRoutingKey, basicProperties, Encoding.UTF8.GetBytes(message.Body));
|
||||
session.Close();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Dispose();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (this.currentConnecton != null)
|
||||
{
|
||||
this.currentConnecton.Close();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.currentConnecton = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
{
|
||||
"Scripts":
|
||||
[
|
||||
"ZnVuY3Rpb24gdDMgeyAxMjsgcmV0dXJuICJ0ZXN0IiB9",
|
||||
"ZnVuY3Rpb24gTmV3LVBlcnNvbigpDQp7DQogIHBhcmFtICgkRmlyc3ROYW1lLCAkTGFzdE5hbWUsICRQaG9uZSkNCg0KICAkcGVyc29uID0gbmV3LW9iamVjdCBQU09iamVjdA0KDQogICRwZXJzb24gfCBhZGQtbWVtYmVyIC10eXBlIE5vdGVQcm9wZXJ0eSAtTmFtZSBGaXJzdCAtVmFsdWUgJEZpcnN0TmFtZQ0KICAkcGVyc29uIHwgYWRkLW1lbWJlciAtdHlwZSBOb3RlUHJvcGVydHkgLU5hbWUgTGFzdCAtVmFsdWUgJExhc3ROYW1lDQogICRwZXJzb24gfCBhZGQtbWVtYmVyIC10eXBlIE5vdGVQcm9wZXJ0eSAtTmFtZSBQaG9uZSAtVmFsdWUgJFBob25lDQoNCiAgcmV0dXJuICRwZXJzb24NCn0=",
|
||||
"ZnVuY3Rpb24gVGVzdFRocm93KCkNCnsNCglUaHJvdyBbc3lzdGVtLkluZGV4T3V0T2ZSYW5nZUV4Y2VwdGlvbl0gDQp9"
|
||||
],
|
||||
"Commands" :
|
||||
[
|
||||
{
|
||||
"Name": "New-Person",
|
||||
"Arguments" :
|
||||
{
|
||||
"FirstName": "MyFirstName",
|
||||
"LastName": "MyLastName",
|
||||
"Phone": "123-456"
|
||||
}
|
||||
|
||||
},
|
||||
{
|
||||
"Name": "t3",
|
||||
"Arguments" :
|
||||
{
|
||||
}
|
||||
|
||||
},
|
||||
{
|
||||
"Name": "Get-Date",
|
||||
|
||||
},
|
||||
{
|
||||
"Name": "TestThrow",
|
||||
|
||||
}
|
||||
],
|
||||
"RebootOnCompletion": 0
|
||||
}
|
|
@ -1,111 +0,0 @@
|
|||
using System;
|
||||
using System.Configuration.Install;
|
||||
using System.Reflection;
|
||||
using System.ServiceProcess;
|
||||
using NLog;
|
||||
|
||||
namespace Mirantis.Keero.WindowsAgent
|
||||
{
|
||||
public class ServiceManager
|
||||
{
|
||||
private readonly string serviceName;
|
||||
|
||||
public ServiceManager(string serviceName)
|
||||
{
|
||||
this.serviceName = serviceName;
|
||||
}
|
||||
|
||||
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
public bool Restart(string[] args, TimeSpan timeout)
|
||||
{
|
||||
var service = new ServiceController(serviceName);
|
||||
try
|
||||
{
|
||||
var millisec1 = TimeSpan.FromMilliseconds(Environment.TickCount);
|
||||
|
||||
service.Stop();
|
||||
service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);
|
||||
Log.Info("Service is stopped");
|
||||
|
||||
// count the rest of the timeout
|
||||
var millisec2 = TimeSpan.FromMilliseconds(Environment.TickCount);
|
||||
timeout = timeout - (millisec2 - millisec1);
|
||||
|
||||
service.Start(args);
|
||||
service.WaitForStatus(ServiceControllerStatus.Running, timeout);
|
||||
Log.Info("Service has started");
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.ErrorException("Cannot restart service " + serviceName, ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Stop(TimeSpan timeout)
|
||||
{
|
||||
var service = new ServiceController(serviceName);
|
||||
try
|
||||
{
|
||||
service.Stop();
|
||||
service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.ErrorException("Cannot stop service " + serviceName, ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Start(string[] args, TimeSpan timeout)
|
||||
{
|
||||
var service = new ServiceController(serviceName);
|
||||
try
|
||||
{
|
||||
service.Start(args);
|
||||
service.WaitForStatus(ServiceControllerStatus.Running, timeout);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.ErrorException("Cannot start service " + serviceName, ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Install()
|
||||
{
|
||||
try
|
||||
{
|
||||
ManagedInstallerClass.InstallHelper(
|
||||
new string[] { Assembly.GetEntryAssembly().Location });
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Log.ErrorException("Cannot install service " + serviceName, ex);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Uninstall()
|
||||
{
|
||||
try
|
||||
{
|
||||
ManagedInstallerClass.InstallHelper(
|
||||
new string[] { "/u", Assembly.GetEntryAssembly().Location });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.ErrorException("Cannot uninstall service " + serviceName, ex);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{F7E2A8D5-6D24-4651-A4BC-1024D59F4903}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Mirantis.Keero.WindowsAgent</RootNamespace>
|
||||
<AssemblyName>WindowsAgent</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json">
|
||||
<HintPath>..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog">
|
||||
<HintPath>..\packages\NLog.2.0.0.2000\lib\net40\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RabbitMQ.Client">
|
||||
<HintPath>..\packages\RabbitMQ.Client.3.0.2\lib\net30\RabbitMQ.Client.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Configuration.Install" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\3.0\System.Management.Automation.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.ServiceProcess" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ExecutionPlan.cs" />
|
||||
<Compile Include="MqMessage.cs" />
|
||||
<Compile Include="PlanExecutor.cs" />
|
||||
<Compile Include="Program.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="RabbitMqClient.cs" />
|
||||
<Compile Include="ServiceManager.cs" />
|
||||
<Compile Include="WindowsService.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="WindowsServiceInstaller.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="SampleExecutionPlan.json" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>$(SolutionDir)Tools\nuget install $(ProjectDir)packages.config -o $(SolutionDir)Packages</PreBuildEvent>
|
||||
</PropertyGroup>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
|
@ -1,95 +0,0 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.ServiceProcess;
|
||||
using NLog;
|
||||
|
||||
namespace Mirantis.Keero.WindowsAgent
|
||||
{
|
||||
public abstract class WindowsService : ServiceBase
|
||||
{
|
||||
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
|
||||
public bool RunningAsService { get; private set; }
|
||||
|
||||
protected static void Start(WindowsService service, string[] arguments)
|
||||
{
|
||||
Directory.SetCurrentDirectory(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location));
|
||||
|
||||
if (arguments.Contains("/install", StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
new ServiceManager(service.ServiceName).Install();
|
||||
}
|
||||
else if (arguments.Contains("/uninstall", StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
new ServiceManager(service.ServiceName).Uninstall();
|
||||
}
|
||||
else if (arguments.Contains("/start", StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
new ServiceManager(service.ServiceName).Start(Environment.GetCommandLineArgs(), TimeSpan.FromMinutes(1));
|
||||
}
|
||||
else if (arguments.Contains("/stop", StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
new ServiceManager(service.ServiceName).Stop(TimeSpan.FromMinutes(1));
|
||||
}
|
||||
else if (arguments.Contains("/restart", StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
new ServiceManager(service.ServiceName).Restart(Environment.GetCommandLineArgs(), TimeSpan.FromMinutes(1));
|
||||
}
|
||||
else if (!arguments.Contains("/console", StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
service.RunningAsService = true;
|
||||
Run(service);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
service.RunningAsService = false;
|
||||
Console.Title = service.ServiceName;
|
||||
service.OnStart(Environment.GetCommandLineArgs());
|
||||
service.WaitForExitSignal();
|
||||
}
|
||||
finally
|
||||
{
|
||||
service.OnStop();
|
||||
service.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected WindowsService()
|
||||
{
|
||||
var displayNameAttribute =
|
||||
this.GetType().GetCustomAttributes(typeof (DisplayNameAttribute), false).Cast<DisplayNameAttribute>().
|
||||
FirstOrDefault();
|
||||
if(displayNameAttribute != null)
|
||||
{
|
||||
ServiceName = displayNameAttribute.DisplayName;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected virtual void WaitForExitSignal()
|
||||
{
|
||||
Console.WriteLine("Press ESC to exit");
|
||||
while (Console.ReadKey(true).Key != ConsoleKey.Escape)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnStart(string[] args)
|
||||
{
|
||||
Log.Info("Service {0} started", ServiceName);
|
||||
|
||||
base.OnStart(args);
|
||||
}
|
||||
|
||||
protected override void OnStop()
|
||||
{
|
||||
Log.Info("Service {0} exited", ServiceName);
|
||||
base.OnStop();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
using System.ComponentModel;
|
||||
using System.Configuration.Install;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.ServiceProcess;
|
||||
|
||||
namespace Mirantis.Keero.WindowsAgent
|
||||
{
|
||||
[RunInstaller(true)]
|
||||
public class WindowsServiceInstaller : Installer
|
||||
{
|
||||
public WindowsServiceInstaller()
|
||||
{
|
||||
var processInstaller = new ServiceProcessInstaller { Account = ServiceAccount.LocalSystem };
|
||||
foreach (var type in Assembly.GetEntryAssembly().GetExportedTypes().Where(t => t.IsSubclassOf(typeof(ServiceBase))))
|
||||
{
|
||||
var nameAttribute = type.GetCustomAttributes(typeof (DisplayNameAttribute), false)
|
||||
.Cast<DisplayNameAttribute>().FirstOrDefault();
|
||||
if(nameAttribute == null) continue;
|
||||
var serviceInstaller = new ServiceInstaller {
|
||||
StartType = ServiceStartMode.Automatic,
|
||||
ServiceName = nameAttribute.DisplayName,
|
||||
DisplayName = nameAttribute.DisplayName
|
||||
};
|
||||
var descriptionAttribute = type.GetCustomAttributes(typeof(DescriptionAttribute), false)
|
||||
.Cast<DescriptionAttribute>().FirstOrDefault();
|
||||
if(descriptionAttribute != null)
|
||||
{
|
||||
serviceInstaller.Description = descriptionAttribute.Description;
|
||||
}
|
||||
|
||||
Installers.Add(serviceInstaller);
|
||||
}
|
||||
|
||||
Installers.Add(processInstaller);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="4.5.11" targetFramework="net45" />
|
||||
<package id="NLog" version="2.0.0.2000" targetFramework="net45" />
|
||||
<package id="RabbitMQ.Client" version="3.0.2" targetFramework="net45" />
|
||||
</packages>
|
|
@ -1,4 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<repositories>
|
||||
<repository path="..\WindowsAgent\packages.config" />
|
||||
</repositories>
|
|
@ -1,23 +0,0 @@
|
|||
#IntelJ Idea
|
||||
.idea/
|
||||
|
||||
#virtualenv
|
||||
.venv/
|
||||
|
||||
#Build results
|
||||
build/
|
||||
dist/
|
||||
*.egg-info/
|
||||
|
||||
#Python
|
||||
*.pyc
|
||||
|
||||
#Translation build
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
#SQLite Database files
|
||||
*.sqlite
|
||||
|
||||
#Autogenerated Documentation
|
||||
doc/source/api
|
|
@ -1,7 +0,0 @@
|
|||
Glazier API README
|
||||
=====================
|
||||
Glazier API is a project that provides access to engine via API.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
* `Glazier <http://glazier.mirantis.com>`__
|
|
@ -1 +0,0 @@
|
|||
[python: **.py]
|
|
@ -1,54 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.from oslo.config import cfg
|
||||
|
||||
import gettext
|
||||
import os
|
||||
import sys
|
||||
|
||||
# If ../glazierapi/__init__.py exists, add ../ to Python search path, so that
|
||||
# it will override what happens to be installed in /usr/(local/)lib/python...
|
||||
from glazierapi.common.service import TaskResultHandlerService
|
||||
|
||||
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
|
||||
os.pardir,
|
||||
os.pardir))
|
||||
if os.path.exists(os.path.join(possible_topdir, 'portas', '__init__.py')):
|
||||
sys.path.insert(0, possible_topdir)
|
||||
|
||||
from glazierapi.common import config
|
||||
from glazierapi.openstack.common import log
|
||||
from glazierapi.openstack.common import wsgi
|
||||
from glazierapi.openstack.common import service
|
||||
|
||||
gettext.install('glazierapi', './glazierapi/locale', unicode=1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
config.parse_args()
|
||||
log.setup('glazierapi')
|
||||
|
||||
launcher = service.ServiceLauncher()
|
||||
|
||||
api_service = wsgi.Service(config.load_paste_app(),
|
||||
port=config.CONF.bind_port,
|
||||
host=config.CONF.bind_host)
|
||||
|
||||
launcher.launch_service(api_service)
|
||||
launcher.launch_service(TaskResultHandlerService())
|
||||
launcher.wait()
|
||||
except RuntimeError, e:
|
||||
sys.stderr.write("ERROR: %s\n" % e)
|
||||
sys.exit(1)
|
|
@ -1,2 +0,0 @@
|
|||
[theme]
|
||||
inherit = default
|
|
@ -1,241 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2010 OpenStack Foundation.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
#
|
||||
# Portas documentation build configuration file, created by
|
||||
# sphinx-quickstart on Tue February 28 13:50:15 2013.
|
||||
#
|
||||
# This file is execfile()'d with the current directory set to its containing
|
||||
# dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
sys.path = [os.path.abspath('../../glazierapi'),
|
||||
os.path.abspath('../..'),
|
||||
os.path.abspath('../../bin')] + sys.path
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = ['sphinx.ext.autodoc',
|
||||
'sphinx.ext.intersphinx',
|
||||
'sphinx.ext.coverage',
|
||||
'sphinx.ext.pngmath',
|
||||
'sphinx.ext.ifconfig',
|
||||
'sphinx.ext.graphviz']
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = []
|
||||
if os.getenv('HUDSON_PUBLISH_DOCS'):
|
||||
templates_path = ['_ga', '_templates']
|
||||
else:
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The encoding of source files.
|
||||
#source_encoding = 'utf-8'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'Glazier APIs'
|
||||
copyright = u'2013, Mirantis, Inc'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
from glazierapi.version import version_info as portas_version
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = portas_version.version_string_with_vcs()
|
||||
# The short X.Y version.
|
||||
version = portas_version.canonical_version_string()
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#language = None
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
#today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
#today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of documents that shouldn't be included in the build.
|
||||
#unused_docs = []
|
||||
|
||||
# List of directories, relative to source directory, that shouldn't be searched
|
||||
# for source files.
|
||||
exclude_trees = ['api']
|
||||
|
||||
# The reST default role (for this markup: `text`) to use for all documents.
|
||||
#default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
show_authors = True
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
modindex_common_prefix = ['glazierapi.']
|
||||
|
||||
# -- Options for man page output --------------------------------------------
|
||||
|
||||
# Grouping the document tree for man pages.
|
||||
# List of tuples 'sourcefile', 'target', u'title', u'Authors name', 'manual'
|
||||
|
||||
man_pages = [
|
||||
('man/glazierapi', 'glazier-api', u'Glazier API Server',
|
||||
[u'Mirantis, Inc'], 1)
|
||||
]
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. Major themes that come with
|
||||
# Sphinx are currently 'default' and 'sphinxdoc'.
|
||||
html_theme_path = ["."]
|
||||
html_theme = '_theme'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
#html_theme_path = ['_theme']
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
#html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
#html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#html_logo = None
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
#html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
#html_last_updated_fmt = '%b %d, %Y'
|
||||
git_cmd = "git log --pretty=format:'%ad, commit %h' --date=local -n1"
|
||||
html_last_updated_fmt = os.popen(git_cmd).read()
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
#html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
#html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
html_use_modindex = False
|
||||
|
||||
# If false, no index is generated.
|
||||
html_use_index = False
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
#html_show_sourcelink = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
#html_use_opensearch = ''
|
||||
|
||||
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#html_file_suffix = ''
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'glazierapidoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output ------------------------------------------------
|
||||
|
||||
# The paper size ('letter' or 'a4').
|
||||
#latex_paper_size = 'letter'
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#latex_font_size = '10pt'
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'Glazier.tex', u'Glazier Documentation',
|
||||
u'Mirantis, Inc', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
#latex_use_parts = False
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#latex_preamble = ''
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#latex_use_modindex = True
|
||||
|
||||
# Example configuration for intersphinx: refer to the Python standard library.
|
||||
intersphinx_mapping = {'python': ('http://docs.python.org/', None)}
|
|
@ -1,114 +0,0 @@
|
|||
..
|
||||
Copyright (c) 2013 Mirantis, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
not use this file except in compliance with the License. You may obtain
|
||||
a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
==============================================
|
||||
Welcome to Glazier API Service!
|
||||
==============================================
|
||||
|
||||
Glazier API is a project that provides access to engine via API.
|
||||
|
||||
This document describes Glazier API for contributors of the project,
|
||||
and assumes that you are already familiar with Glazier API from an
|
||||
`end-user perspective`_.
|
||||
|
||||
.. _`end-user perspective`: http://glazier.mirantis.com/
|
||||
|
||||
This documentation is generated by the Sphinx toolkit and lives in the source
|
||||
tree.
|
||||
|
||||
Installation Guide
|
||||
==================
|
||||
Install
|
||||
-------
|
||||
1. Check out sources to some directory (<home>/glazier)::
|
||||
|
||||
user@work:~/$ git clone ssh://<user>@gerrit.mirantis.com:29418/keero/keero.git
|
||||
|
||||
2. Install Glazier API::
|
||||
|
||||
user@work:~/$ cd glazier/api && sudo python setup.py install
|
||||
|
||||
Configure
|
||||
---------
|
||||
1. Open first configuration file for editing::
|
||||
|
||||
user@work:~/$ cd glazier/api/etc && nano glazier-api.conf
|
||||
|
||||
2. Configure according to you environment (please note rabbitmq section)::
|
||||
|
||||
[DEFAULT]
|
||||
# Show more verbose log output (sets INFO log level output)
|
||||
verbose = True
|
||||
# Show debugging output in logs (sets DEBUG log level output)
|
||||
debug = True
|
||||
# Address to bind the server to
|
||||
bind_host = 0.0.0.0
|
||||
# Port the bind the server to
|
||||
bind_port = 8082
|
||||
# Log to this file. Make sure the user running skeleton-api has
|
||||
# permissions to write to this file!
|
||||
log_file = /tmp/glazier-api.log
|
||||
#A valid SQLAlchemy connection string for the metadata database
|
||||
sql_connection = sqlite:///glazier.sqlite
|
||||
|
||||
[reports]
|
||||
results_exchange = task-results
|
||||
results_queue = task-results
|
||||
reports_exchange = task-reports
|
||||
reports_queue = task-reports
|
||||
|
||||
[rabbitmq]
|
||||
host = localhost
|
||||
port = 5672
|
||||
virtual_host = keero
|
||||
login = keero
|
||||
password = keero
|
||||
|
||||
3. Open second configuration file for editing::
|
||||
|
||||
smelikyan@work:~/cd glazier/api/etc && nano glazier-api.conf
|
||||
|
||||
4. Configure according to you environment (please note filter:authtoken section)::
|
||||
|
||||
[pipeline:glazier-api]
|
||||
pipeline = authtoken context apiv1app
|
||||
[app:apiv1app]
|
||||
paste.app_factory = glazierapi.api.v1.router:API.factory
|
||||
[filter:context]
|
||||
paste.filter_factory = glazierapi.api.middleware.context:ContextMiddleware.factory
|
||||
|
||||
[filter:authtoken]
|
||||
paste.filter_factory = keystoneclient.middleware.auth_token:filter_factory
|
||||
auth_host = localhost
|
||||
auth_port = 35357
|
||||
auth_protocol = http
|
||||
admin_tenant_name = admin
|
||||
admin_user = admin
|
||||
admin_password = password
|
||||
signing_dir = /tmp/keystone-signing-glazierapi
|
||||
|
||||
Run
|
||||
----
|
||||
Run Glazier API and supply valid configuration file::
|
||||
|
||||
user@work:~/$ glazier-api --config-file=./glazier/api/etc/glazier-api.conf
|
||||
|
||||
Man Pages
|
||||
=========
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
man/glazierapi
|
|
@ -1,69 +0,0 @@
|
|||
..
|
||||
Copyright (c) 2013 Mirantis, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
not use this file except in compliance with the License. You may obtain
|
||||
a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
==========
|
||||
glazier-api
|
||||
==========
|
||||
|
||||
-----------------------------
|
||||
Glazier API Server
|
||||
-----------------------------
|
||||
|
||||
:Author: smelikyan@mirantis.com
|
||||
:Date: 2013-04-04
|
||||
:Copyright: Mirantis, Inc.
|
||||
:Version: 2013.1-dev
|
||||
:Manual section: 1
|
||||
:Manual group: cloud computing
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
========
|
||||
|
||||
glazier-api [options]
|
||||
|
||||
DESCRIPTION
|
||||
===========
|
||||
|
||||
glazier-api is a server daemon that serves the Glazier API
|
||||
|
||||
OPTIONS
|
||||
=======
|
||||
|
||||
**General options**
|
||||
|
||||
**-v, --verbose**
|
||||
Print more verbose output
|
||||
|
||||
**--config-file**
|
||||
Config file used for running service
|
||||
|
||||
**--bind-host=HOST**
|
||||
Address of host running ``glazier-api``. Defaults to `0.0.0.0`.
|
||||
|
||||
**--bind-port=PORT**
|
||||
Port that ``glazier-api`` listens on. Defaults to `8082`.
|
||||
|
||||
|
||||
FILES
|
||||
=====
|
||||
|
||||
* /etc/glazier/glazier-api.conf
|
||||
* /etc/glazier/glazier-api-paste.conf
|
||||
|
||||
SEE ALSO
|
||||
========
|
||||
|
||||
* `Glazier <http://glazier.mirantis.com>`__
|
|
@ -1,18 +0,0 @@
|
|||
[pipeline:glazier-api]
|
||||
pipeline = authtoken context apiv1app
|
||||
|
||||
[app:apiv1app]
|
||||
paste.app_factory = glazierapi.api.v1.router:API.factory
|
||||
|
||||
[filter:context]
|
||||
paste.filter_factory = glazierapi.api.middleware.context:ContextMiddleware.factory
|
||||
|
||||
[filter:authtoken]
|
||||
paste.filter_factory = keystoneclient.middleware.auth_token:filter_factory
|
||||
auth_host = localhost
|
||||
auth_port = 35357
|
||||
auth_protocol = http
|
||||
admin_tenant_name = admin
|
||||
admin_user = admin
|
||||
admin_password = password
|
||||
signing_dir = /tmp/keystone-signing-portas
|
|
@ -1,32 +0,0 @@
|
|||
[DEFAULT]
|
||||
# Show more verbose log output (sets INFO log level output)
|
||||
verbose = True
|
||||
|
||||
# Show debugging output in logs (sets DEBUG log level output)
|
||||
debug = True
|
||||
|
||||
# Address to bind the server to
|
||||
bind_host = 0.0.0.0
|
||||
|
||||
# Port the bind the server to
|
||||
bind_port = 8082
|
||||
|
||||
# Log to this file. Make sure the user running skeleton-api has
|
||||
# permissions to write to this file!
|
||||
log_file = /tmp/portas-api.log
|
||||
|
||||
#A valid SQLAlchemy connection string for the metadata database
|
||||
sql_connection = sqlite:///glazier.sqlite
|
||||
|
||||
[reports]
|
||||
results_exchange = task-results
|
||||
results_queue = task-results
|
||||
reports_exchange = task-reports
|
||||
reports_queue = task-reports
|
||||
|
||||
[rabbitmq]
|
||||
host = localhost
|
||||
port = 5672
|
||||
virtual_host = keero
|
||||
login = keero
|
||||
password = keero
|
|
@ -1,13 +0,0 @@
|
|||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
|
@ -1,14 +0,0 @@
|
|||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.from oslo.config import cfg
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.from oslo.config import cfg
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.from oslo.config import cfg
|
||||
|
||||
|
||||
import json
|
||||
from oslo.config import cfg
|
||||
|
||||
import webob.exc
|
||||
|
||||
from glazierapi.openstack.common import wsgi
|
||||
import glazierapi.context
|
||||
import glazierapi.openstack.common.log as logging
|
||||
|
||||
CONF = cfg.CONF
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class BaseContextMiddleware(wsgi.Middleware):
|
||||
def process_response(self, resp):
|
||||
try:
|
||||
request_id = resp.request.context.request_id
|
||||
except AttributeError:
|
||||
LOG.warn(_('Unable to retrieve request id from context'))
|
||||
else:
|
||||
resp.headers['x-openstack-request-id'] = 'req-%s' % request_id
|
||||
return resp
|
||||
|
||||
|
||||
class ContextMiddleware(BaseContextMiddleware):
|
||||
def process_request(self, req):
|
||||
"""Convert authentication information into a request context
|
||||
|
||||
Generate a glazierapi.context.RequestContext object from the available
|
||||
authentication headers and store on the 'context' attribute
|
||||
of the req object.
|
||||
|
||||
:param req: wsgi request object that will be given the context object
|
||||
:raises webob.exc.HTTPUnauthorized: when value of the X-Identity-Status
|
||||
header is not 'Confirmed' and
|
||||
anonymous access is disallowed
|
||||
"""
|
||||
if req.headers.get('X-Identity-Status') == 'Confirmed':
|
||||
roles_header = req.headers.get('X-Roles', '')
|
||||
roles = [r.strip().lower() for r in roles_header.split(',')]
|
||||
|
||||
#NOTE(bcwaldon): This header is deprecated in favor of X-Auth-Token
|
||||
deprecated_token = req.headers.get('X-Storage-Token')
|
||||
|
||||
service_catalog = None
|
||||
if req.headers.get('X-Service-Catalog') is not None:
|
||||
try:
|
||||
catalog_header = req.headers.get('X-Service-Catalog')
|
||||
service_catalog = json.loads(catalog_header)
|
||||
except ValueError:
|
||||
raise webob.exc.HTTPInternalServerError(
|
||||
_('Invalid service catalog json.'))
|
||||
|
||||
kwargs = {
|
||||
'user': req.headers.get('X-User-Id'),
|
||||
'tenant': req.headers.get('X-Tenant-Id'),
|
||||
'roles': roles,
|
||||
'auth_token': req.headers.get('X-Auth-Token',
|
||||
deprecated_token),
|
||||
'service_catalog': service_catalog,
|
||||
'session': req.headers.get('X-Configuration-Session')
|
||||
}
|
||||
req.context = glazierapi.context.RequestContext(**kwargs)
|
||||
else:
|
||||
raise webob.exc.HTTPUnauthorized()
|
||||
|
||||
@classmethod
|
||||
def factory(cls, global_conf, **local_conf):
|
||||
def filter(app):
|
||||
return cls(app)
|
||||
return filter
|
|
@ -1,110 +0,0 @@
|
|||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.from oslo.config import cfg
|
||||
|
||||
from glazierapi.db.models import Session, Environment, Status
|
||||
from glazierapi.db.session import get_session
|
||||
|
||||
|
||||
def get_draft(environment_id=None, session_id=None):
|
||||
unit = get_session()
|
||||
#TODO: When session is deployed should be returned env.description
|
||||
if session_id:
|
||||
session = unit.query(Session).get(session_id)
|
||||
return session.description
|
||||
else:
|
||||
environment = unit.query(Environment).get(environment_id)
|
||||
return environment.description
|
||||
|
||||
|
||||
def save_draft(session_id, draft):
|
||||
unit = get_session()
|
||||
session = unit.query(Session).get(session_id)
|
||||
|
||||
session.description = draft
|
||||
session.save(unit)
|
||||
|
||||
|
||||
def get_env_status(environment_id, session_id):
|
||||
status = 'draft'
|
||||
|
||||
unit = get_session()
|
||||
|
||||
if not session_id:
|
||||
variants = ['open', 'deploying']
|
||||
session = unit.query(Session).filter(
|
||||
Session.environment_id == environment_id and
|
||||
Session.state.in_(variants)
|
||||
).first()
|
||||
if session:
|
||||
session_id = session.id
|
||||
else:
|
||||
return status
|
||||
|
||||
session_state = unit.query(Session).get(session_id).state
|
||||
reports_count = unit.query(Status).filter_by(environment_id=environment_id,
|
||||
session_id=session_id).count()
|
||||
|
||||
if session_state == 'deployed':
|
||||
status = 'finished'
|
||||
|
||||
if session_state == 'deploying' and reports_count > 1:
|
||||
status = 'pending'
|
||||
|
||||
draft = get_draft(environment_id, session_id)
|
||||
|
||||
if not 'services' in draft:
|
||||
return 'pending'
|
||||
|
||||
def get_statuses(type):
|
||||
if type in draft['services']:
|
||||
services = draft['services'][type]
|
||||
return [get_service_status(environment_id,
|
||||
session_id,
|
||||
service) for service in services]
|
||||
else:
|
||||
return []
|
||||
|
||||
is_inprogress = filter(lambda item: item == 'inprogress',
|
||||
get_statuses('activeDirectories') +
|
||||
get_statuses('webServers'))
|
||||
|
||||
if session_state == 'deploying' and is_inprogress > 1:
|
||||
status = 'inprogress'
|
||||
|
||||
return status
|
||||
|
||||
|
||||
def get_service_status(environment_id, session_id, service):
|
||||
status = 'draft'
|
||||
|
||||
unit = get_session()
|
||||
session_state = unit.query(Session).get(session_id).state
|
||||
|
||||
entities = [u['id'] for u in service['units']]
|
||||
reports_count = unit.query(Status).filter(
|
||||
Status.environment_id == environment_id
|
||||
and Status.session_id == session_id
|
||||
and Status.entity_id.in_(entities)
|
||||
).count()
|
||||
|
||||
if session_state == 'deployed':
|
||||
status = 'finished'
|
||||
|
||||
if session_state == 'deploying' and reports_count == 0:
|
||||
status = 'pending'
|
||||
|
||||
if session_state == 'deploying' and reports_count > 0:
|
||||
status = 'inprogress'
|
||||
|
||||
return status
|
|
@ -1,85 +0,0 @@
|
|||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.from oslo.config import cfg
|
||||
|
||||
from glazierapi import utils
|
||||
from glazierapi.api.v1 import save_draft, get_draft, get_service_status
|
||||
from glazierapi.common import uuidutils
|
||||
from glazierapi.openstack.common import wsgi, timeutils
|
||||
from glazierapi.openstack.common import log as logging
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Controller(object):
|
||||
def index(self, request, environment_id):
|
||||
log.debug(_('ActiveDirectory:Index <EnvId: {0}>'.
|
||||
format(environment_id)))
|
||||
|
||||
draft = prepare_draft(get_draft(environment_id,
|
||||
request.context.session))
|
||||
|
||||
for dc in draft['services']['activeDirectories']:
|
||||
dc['status'] = get_service_status(environment_id,
|
||||
request.context.session,
|
||||
dc)
|
||||
|
||||
return {'activeDirectories': draft['services']['activeDirectories']}
|
||||
|
||||
@utils.verify_session
|
||||
def create(self, request, environment_id, body):
|
||||
log.debug(_('ActiveDirectory:Create <EnvId: {0}, Body: {1}>'.
|
||||
format(environment_id, body)))
|
||||
|
||||
draft = get_draft(session_id=request.context.session)
|
||||
|
||||
active_directory = body.copy()
|
||||
active_directory['id'] = uuidutils.generate_uuid()
|
||||
active_directory['created'] = str(timeutils.utcnow())
|
||||
active_directory['updated'] = str(timeutils.utcnow())
|
||||
|
||||
unit_count = 0
|
||||
for unit in active_directory['units']:
|
||||
unit_count += 1
|
||||
unit['id'] = uuidutils.generate_uuid()
|
||||
unit['name'] = 'dc{0}'.format(unit_count)
|
||||
|
||||
draft = prepare_draft(draft)
|
||||
draft['services']['activeDirectories'].append(active_directory)
|
||||
save_draft(request.context.session, draft)
|
||||
|
||||
return active_directory
|
||||
|
||||
def delete(self, request, environment_id, active_directory_id):
|
||||
log.debug(_('ActiveDirectory:Delete <EnvId: {0}, Id: {1}>'.
|
||||
format(environment_id, active_directory_id)))
|
||||
|
||||
draft = get_draft(request.context.session)
|
||||
items = [service for service in draft['services']['activeDirectories']
|
||||
if service['id'] != active_directory_id]
|
||||
draft['services']['activeDirectories'] = items
|
||||
save_draft(request.context.session, draft)
|
||||
|
||||
|
||||
def prepare_draft(draft):
|
||||
if not 'services' in draft:
|
||||
draft['services'] = {}
|
||||
|
||||
if not 'activeDirectories' in draft['services']:
|
||||
draft['services']['activeDirectories'] = []
|
||||
|
||||
return draft
|
||||
|
||||
|
||||
def create_resource():
|
||||
return wsgi.Resource(Controller())
|
|
@ -1,132 +0,0 @@
|
|||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.from oslo.config import cfg
|
||||
|
||||
from amqplib.client_0_8 import Message
|
||||
import anyjson
|
||||
import eventlet
|
||||
from webob import exc
|
||||
from glazierapi.common import config
|
||||
from glazierapi.api.v1 import get_env_status
|
||||
from glazierapi.db.session import get_session
|
||||
from glazierapi.db.models import Environment
|
||||
from glazierapi.openstack.common import wsgi
|
||||
from glazierapi.openstack.common import log as logging
|
||||
|
||||
amqp = eventlet.patcher.import_patched('amqplib.client_0_8')
|
||||
rabbitmq = config.CONF.rabbitmq
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Controller(object):
|
||||
def index(self, request):
|
||||
log.debug(_('Environments:List'))
|
||||
|
||||
#Only environments from same tenant as users should be shown
|
||||
filters = {'tenant_id': request.context.tenant}
|
||||
|
||||
session = get_session()
|
||||
environments = session.query(Environment).filter_by(**filters)
|
||||
environments = [env.to_dict() for env in environments]
|
||||
|
||||
for env in environments:
|
||||
env['status'] = get_env_status(env['id'], request.context.session)
|
||||
|
||||
return {"environments": environments}
|
||||
|
||||
def create(self, request, body):
|
||||
log.debug(_('Environments:Create <Body {0}>'.format(body)))
|
||||
|
||||
#tagging environment by tenant_id for later checks
|
||||
params = body.copy()
|
||||
params['tenant_id'] = request.context.tenant
|
||||
|
||||
environment = Environment()
|
||||
environment.update(params)
|
||||
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
session.add(environment)
|
||||
|
||||
#saving environment as Json to itself
|
||||
environment.update({"description": environment.to_dict()})
|
||||
environment.save(session)
|
||||
|
||||
return environment.to_dict()
|
||||
|
||||
def show(self, request, environment_id):
|
||||
log.debug(_('Environments:Show <Id: {0}>'.format(environment_id)))
|
||||
|
||||
session = get_session()
|
||||
environment = session.query(Environment).get(environment_id)
|
||||
|
||||
if environment.tenant_id != request.context.tenant:
|
||||
log.info('User is not authorized to access this tenant resources.')
|
||||
raise exc.HTTPUnauthorized
|
||||
|
||||
env = environment.to_dict()
|
||||
env['status'] = get_env_status(environment_id, request.context.session)
|
||||
|
||||
return env
|
||||
|
||||
def update(self, request, environment_id, body):
|
||||
log.debug(_('Environments:Update <Id: {0}, Body: {1}>'.
|
||||
format(environment_id, body)))
|
||||
|
||||
session = get_session()
|
||||
environment = session.query(Environment).get(environment_id)
|
||||
|
||||
if environment.tenant_id != request.context.tenant:
|
||||
log.info('User is not authorized to access this tenant resources.')
|
||||
raise exc.HTTPUnauthorized
|
||||
|
||||
environment.update(body)
|
||||
environment.save(session)
|
||||
|
||||
return environment.to_dict()
|
||||
|
||||
def delete(self, request, environment_id):
|
||||
log.debug(_('Environments:Delete <Id: {0}>'.format(environment_id)))
|
||||
|
||||
session = get_session()
|
||||
environment = session.query(Environment).get(environment_id)
|
||||
|
||||
with session.begin():
|
||||
session.delete(environment)
|
||||
|
||||
#preparing data for removal from conductor
|
||||
env = environment.description
|
||||
env['services'] = []
|
||||
env['deleted'] = True
|
||||
#Set X-Auth-Token for conductor
|
||||
env['token'] = request.context.auth_token
|
||||
|
||||
connection = amqp.Connection('{0}:{1}'.
|
||||
format(rabbitmq.host, rabbitmq.port),
|
||||
virtual_host=rabbitmq.virtual_host,
|
||||
userid=rabbitmq.login,
|
||||
password=rabbitmq.password,
|
||||
ssl=rabbitmq.use_ssl, insist=True)
|
||||
channel = connection.channel()
|
||||
channel.exchange_declare('tasks', 'direct', durable=True,
|
||||
auto_delete=False)
|
||||
|
||||
channel.basic_publish(Message(body=anyjson.serialize(env)), 'tasks',
|
||||
'tasks')
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def create_resource():
|
||||
return wsgi.Resource(Controller())
|
|
@ -1,106 +0,0 @@
|
|||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.from oslo.config import cfg
|
||||
|
||||
import routes
|
||||
from glazierapi.openstack.common import wsgi
|
||||
from glazierapi.api.v1 import (environments, sessions,
|
||||
active_directories, webservers)
|
||||
|
||||
|
||||
class API(wsgi.Router):
|
||||
@classmethod
|
||||
def factory(cls, global_conf, **local_conf):
|
||||
return cls(routes.Mapper())
|
||||
|
||||
def __init__(self, mapper):
|
||||
environments_resource = environments.create_resource()
|
||||
mapper.connect('/environments',
|
||||
controller=environments_resource,
|
||||
action='index',
|
||||
conditions={'method': ['GET']})
|
||||
mapper.connect('/environments',
|
||||
controller=environments_resource,
|
||||
action='create',
|
||||
conditions={'method': ['POST']})
|
||||
mapper.connect('/environments/{environment_id}',
|
||||
controller=environments_resource,
|
||||
action='update',
|
||||
conditions={'method': ['PUT']})
|
||||
mapper.connect('/environments/{environment_id}',
|
||||
controller=environments_resource,
|
||||
action='show',
|
||||
conditions={'method': ['GET']})
|
||||
mapper.connect('/environments/{environment_id}',
|
||||
controller=environments_resource,
|
||||
action='delete',
|
||||
conditions={'method': ['DELETE']})
|
||||
|
||||
sessions_resource = sessions.create_resource()
|
||||
mapper.connect('/environments/{environment_id}/sessions',
|
||||
controller=sessions_resource,
|
||||
action='index',
|
||||
conditions={'method': ['GET']})
|
||||
mapper.connect('/environments/{environment_id}/configure',
|
||||
controller=sessions_resource,
|
||||
action='configure',
|
||||
conditions={'method': ['POST']})
|
||||
mapper.connect('/environments/{environment_id}/sessions/{session_id}',
|
||||
controller=sessions_resource,
|
||||
action='show',
|
||||
conditions={'method': ['GET']})
|
||||
mapper.connect('/environments/{environment_id}/sessions/{session_id}',
|
||||
controller=sessions_resource,
|
||||
action='delete',
|
||||
conditions={'method': ['DELETE']})
|
||||
mapper.connect('/environments/{environment_id}/sessions/'
|
||||
'{session_id}/reports',
|
||||
controller=sessions_resource,
|
||||
action='reports',
|
||||
conditions={'method': ['GET']})
|
||||
mapper.connect('/environments/{environment_id}/sessions/'
|
||||
'{session_id}/deploy',
|
||||
controller=sessions_resource,
|
||||
action='deploy',
|
||||
conditions={'method': ['POST']})
|
||||
|
||||
activeDirectories_resource = active_directories.create_resource()
|
||||
mapper.connect('/environments/{environment_id}/activeDirectories',
|
||||
controller=activeDirectories_resource,
|
||||
action='index',
|
||||
conditions={'method': ['GET']})
|
||||
mapper.connect('/environments/{environment_id}/activeDirectories',
|
||||
controller=activeDirectories_resource,
|
||||
action='create',
|
||||
conditions={'method': ['POST']})
|
||||
mapper.connect('/environments/{environment_id}/activeDirectories/'
|
||||
'{active_directory_id}',
|
||||
controller=activeDirectories_resource,
|
||||
action='delete',
|
||||
conditions={'method': ['DELETE']})
|
||||
|
||||
webServers_resource = webservers.create_resource()
|
||||
mapper.connect('/environments/{environment_id}/webServers',
|
||||
controller=webServers_resource,
|
||||
action='index',
|
||||
conditions={'method': ['GET']})
|
||||
mapper.connect('/environments/{environment_id}/webServers',
|
||||
controller=webServers_resource,
|
||||
action='create',
|
||||
conditions={'method': ['POST']})
|
||||
mapper.connect('/environments/{environment_id}/webServers/'
|
||||
'{web_server_id}',
|
||||
controller=webServers_resource,
|
||||
action='delete',
|
||||
conditions={'method': ['DELETE']})
|
||||
super(API, self).__init__(mapper)
|
|
@ -1,168 +0,0 @@
|
|||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.from oslo.config import cfg
|
||||
|
||||
from amqplib.client_0_8 import Message
|
||||
import anyjson
|
||||
import eventlet
|
||||
from webob import exc
|
||||
from glazierapi.common import config
|
||||
from glazierapi.db.models import Session, Status, Environment
|
||||
from glazierapi.db.session import get_session
|
||||
from glazierapi.openstack.common import wsgi
|
||||
from glazierapi.openstack.common import log as logging
|
||||
|
||||
amqp = eventlet.patcher.import_patched('amqplib.client_0_8')
|
||||
rabbitmq = config.CONF.rabbitmq
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Controller(object):
|
||||
def index(self, request, environment_id):
|
||||
log.debug(_('Session:List <EnvId: {0}>'.format(environment_id)))
|
||||
|
||||
filters = {'environment_id': environment_id,
|
||||
'user_id': request.context.user}
|
||||
|
||||
unit = get_session()
|
||||
configuration_sessions = unit.query(Session).filter_by(**filters)
|
||||
|
||||
sessions = [session.to_dict() for session in configuration_sessions if
|
||||
session.environment.tenant_id == request.context.tenant]
|
||||
return {"sessions": sessions}
|
||||
|
||||
def configure(self, request, environment_id):
|
||||
log.debug(_('Session:Configure <EnvId: {0}>'.format(environment_id)))
|
||||
|
||||
params = {'environment_id': environment_id,
|
||||
'user_id': request.context.user, 'state': 'open'}
|
||||
|
||||
session = Session()
|
||||
session.update(params)
|
||||
|
||||
unit = get_session()
|
||||
if unit.query(Session).filter(
|
||||
Session.environment_id == environment_id and
|
||||
Session.state.in_(['open', 'deploying'])
|
||||
).first():
|
||||
log.info('There is already open session for this environment')
|
||||
raise exc.HTTPConflict
|
||||
|
||||
#create draft for apply later changes
|
||||
environment = unit.query(Environment).get(environment_id)
|
||||
session.description = environment.description
|
||||
|
||||
with unit.begin():
|
||||
unit.add(session)
|
||||
|
||||
return session.to_dict()
|
||||
|
||||
def show(self, request, environment_id, session_id):
|
||||
log.debug(_('Session:Show <EnvId: {0}, '
|
||||
'SessionId: {1}>'.format(environment_id, session_id)))
|
||||
|
||||
unit = get_session()
|
||||
session = unit.query(Session).get(session_id)
|
||||
|
||||
if session.environment.tenant_id != request.context.tenant:
|
||||
log.info('User is not authorized to access this tenant resources.')
|
||||
raise exc.HTTPUnauthorized
|
||||
|
||||
return session.to_dict()
|
||||
|
||||
def delete(self, request, environment_id, session_id):
|
||||
log.debug(_('Session:Delete <EnvId: {0}, '
|
||||
'SessionId: {1}>'.format(environment_id, session_id)))
|
||||
|
||||
unit = get_session()
|
||||
session = unit.query(Session).get(session_id)
|
||||
|
||||
comment = 'Session object in \'deploying\' state could not be deleted'
|
||||
if session.state == 'deploying':
|
||||
log.info(comment)
|
||||
raise exc.HTTPForbidden(comment=comment)
|
||||
|
||||
with unit.begin():
|
||||
unit.delete(session)
|
||||
|
||||
return None
|
||||
|
||||
def reports(self, request, environment_id, session_id):
|
||||
log.debug(_('Session:Reports <EnvId: {0}, '
|
||||
'SessionId: {1}>'.format(environment_id, session_id)))
|
||||
|
||||
unit = get_session()
|
||||
statuses = unit.query(Status).filter_by(session_id=session_id).all()
|
||||
result = statuses
|
||||
|
||||
if 'service_id' in request.GET:
|
||||
service_id = request.GET['service_id']
|
||||
|
||||
environment = unit.query(Session).get(session_id).description
|
||||
services = []
|
||||
if 'services' in environment and 'activeDirectories' in\
|
||||
environment['services']:
|
||||
services += environment['services']['activeDirectories']
|
||||
|
||||
if 'services' in environment and 'webServers' in\
|
||||
environment['services']:
|
||||
services += environment['services']['webServers']
|
||||
|
||||
service = [service for service in services
|
||||
if service['id'] == service_id][0]
|
||||
|
||||
if service:
|
||||
entities = [u['id'] for u in service['units']]
|
||||
entities.append(service_id)
|
||||
result = []
|
||||
for status in statuses:
|
||||
if status.entity_id in entities:
|
||||
result.append(status)
|
||||
|
||||
return {'reports': [status.to_dict() for status in result]}
|
||||
|
||||
def deploy(self, request, environment_id, session_id):
|
||||
log.debug(_('Session:Deploy <EnvId: {0}, '
|
||||
'SessionId: {1}>'.format(environment_id, session_id)))
|
||||
|
||||
unit = get_session()
|
||||
session = unit.query(Session).get(session_id)
|
||||
|
||||
msg = _('Could not deploy session. Session is already '
|
||||
'deployed or in deployment state')
|
||||
if session.state != 'open':
|
||||
log.warn(msg)
|
||||
|
||||
session.state = 'deploying'
|
||||
session.save(unit)
|
||||
|
||||
#Set X-Auth-Token for conductor
|
||||
env = session.description
|
||||
env['token'] = request.context.auth_token
|
||||
|
||||
connection = amqp.Connection('{0}:{1}'.
|
||||
format(rabbitmq.host, rabbitmq.port),
|
||||
virtual_host=rabbitmq.virtual_host,
|
||||
userid=rabbitmq.login,
|
||||
password=rabbitmq.password,
|
||||
ssl=rabbitmq.use_ssl, insist=True)
|
||||
channel = connection.channel()
|
||||
channel.exchange_declare('tasks', 'direct', durable=True,
|
||||
auto_delete=False)
|
||||
|
||||
channel.basic_publish(Message(body=anyjson.serialize(env)), 'tasks',
|
||||
'tasks')
|
||||
|
||||
|
||||
def create_resource():
|
||||
return wsgi.Resource(Controller())
|
|
@ -1,85 +0,0 @@
|
|||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.from oslo.config import cfg
|
||||
|
||||
from glazierapi import utils
|
||||
from glazierapi.api.v1 import save_draft, get_draft, get_service_status
|
||||
from glazierapi.common import uuidutils
|
||||
from glazierapi.openstack.common import wsgi, timeutils
|
||||
from glazierapi.openstack.common import log as logging
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Controller(object):
|
||||
def index(self, request, environment_id):
|
||||
log.debug(_('WebServer:List <EnvId: {0}>'.format(environment_id)))
|
||||
|
||||
draft = prepare_draft(get_draft(environment_id,
|
||||
request.context.session))
|
||||
|
||||
for dc in draft['services']['webServers']:
|
||||
dc['status'] = get_service_status(environment_id,
|
||||
request.context.session, dc)
|
||||
|
||||
return {'webServers': draft['services']['webServers']}
|
||||
|
||||
@utils.verify_session
|
||||
def create(self, request, environment_id, body):
|
||||
log.debug(_('WebServer:Create <EnvId: {0}, Body: {1}>'.
|
||||
format(environment_id, body)))
|
||||
|
||||
draft = get_draft(session_id=request.context.session)
|
||||
|
||||
webServer = body.copy()
|
||||
webServer['id'] = uuidutils.generate_uuid()
|
||||
webServer['created'] = str(timeutils.utcnow())
|
||||
webServer['updated'] = str(timeutils.utcnow())
|
||||
|
||||
unit_count = 0
|
||||
for unit in webServer['units']:
|
||||
unit_count += 1
|
||||
unit['id'] = uuidutils.generate_uuid()
|
||||
unit['name'] = webServer['name'] + '_instance_' + str(unit_count)
|
||||
|
||||
draft = prepare_draft(draft)
|
||||
draft['services']['webServers'].append(webServer)
|
||||
save_draft(request.context.session, draft)
|
||||
|
||||
return webServer
|
||||
|
||||
@utils.verify_session
|
||||
def delete(self, request, environment_id, web_server_id):
|
||||
log.debug(_('WebServer:Delete <EnvId: {0}, Id: {1}>'.
|
||||
format(environment_id, web_server_id)))
|
||||
|
||||
draft = get_draft(session_id=request.context.session)
|
||||
|
||||
elements = [service for service in draft['services']['webServers'] if
|
||||
service['id'] != web_server_id]
|
||||
draft['services']['webServers'] = elements
|
||||
save_draft(request.context.session, draft)
|
||||
|
||||
|
||||
def prepare_draft(draft):
|
||||
if not 'services' in draft:
|
||||
draft['services'] = {}
|
||||
|
||||
if not 'webServers' in draft['services']:
|
||||
draft['services']['webServers'] = []
|
||||
|
||||
return draft
|
||||
|
||||
|
||||
def create_resource():
|
||||
return wsgi.Resource(Controller())
|
|
@ -1,14 +0,0 @@
|
|||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.from oslo.config import cfg
|
||||
|
|
@ -1,205 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2011 OpenStack LLC.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""
|
||||
Routines for configuring Glance
|
||||
"""
|
||||
|
||||
import logging
|
||||
import logging.config
|
||||
import logging.handlers
|
||||
import os
|
||||
import sys
|
||||
|
||||
from oslo.config import cfg
|
||||
from paste import deploy
|
||||
|
||||
from glazierapi.version import version_info as version
|
||||
|
||||
paste_deploy_opts = [
|
||||
cfg.StrOpt('flavor'),
|
||||
cfg.StrOpt('config_file'),
|
||||
]
|
||||
|
||||
bind_opts = [
|
||||
cfg.StrOpt('bind-host', default='0.0.0.0'),
|
||||
cfg.IntOpt('bind-port', default='8082'),
|
||||
]
|
||||
|
||||
reports_opts = [
|
||||
cfg.StrOpt('results_exchange', default='task-results'),
|
||||
cfg.StrOpt('results_queue', default='task-results'),
|
||||
cfg.StrOpt('reports_exchange', default='task-reports'),
|
||||
cfg.StrOpt('reports_queue', default='task-reports')
|
||||
]
|
||||
|
||||
rabbit_opts = [
|
||||
cfg.StrOpt('host', default='localhost'),
|
||||
cfg.IntOpt('port', default=5672),
|
||||
cfg.BoolOpt('use_ssl', default=False),
|
||||
cfg.StrOpt('login', default='guest'),
|
||||
cfg.StrOpt('password', default='guest'),
|
||||
cfg.StrOpt('virtual_host', default='/'),
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(paste_deploy_opts, group='paste_deploy')
|
||||
CONF.register_cli_opts(bind_opts)
|
||||
# CONF.register_opts(bind_opts)
|
||||
CONF.register_opts(reports_opts, group='reports')
|
||||
CONF.register_opts(rabbit_opts, group='rabbitmq')
|
||||
|
||||
|
||||
CONF.import_opt('verbose', 'glazierapi.openstack.common.log')
|
||||
CONF.import_opt('debug', 'glazierapi.openstack.common.log')
|
||||
CONF.import_opt('log_dir', 'glazierapi.openstack.common.log')
|
||||
CONF.import_opt('log_file', 'glazierapi.openstack.common.log')
|
||||
CONF.import_opt('log_config', 'glazierapi.openstack.common.log')
|
||||
CONF.import_opt('log_format', 'glazierapi.openstack.common.log')
|
||||
CONF.import_opt('log_date_format', 'glazierapi.openstack.common.log')
|
||||
CONF.import_opt('use_syslog', 'glazierapi.openstack.common.log')
|
||||
CONF.import_opt('syslog_log_facility', 'glazierapi.openstack.common.log')
|
||||
|
||||
|
||||
def parse_args(args=None, usage=None, default_config_files=None):
|
||||
CONF(args=args,
|
||||
project='glazierapi',
|
||||
version=version.cached_version_string(),
|
||||
usage=usage,
|
||||
default_config_files=default_config_files)
|
||||
|
||||
|
||||
def setup_logging():
|
||||
"""
|
||||
Sets up the logging options for a log with supplied name
|
||||
"""
|
||||
|
||||
if CONF.log_config:
|
||||
# Use a logging configuration file for all settings...
|
||||
if os.path.exists(CONF.log_config):
|
||||
logging.config.fileConfig(CONF.log_config)
|
||||
return
|
||||
else:
|
||||
raise RuntimeError("Unable to locate specified logging "
|
||||
"config file: %s" % CONF.log_config)
|
||||
|
||||
root_logger = logging.root
|
||||
if CONF.debug:
|
||||
root_logger.setLevel(logging.DEBUG)
|
||||
elif CONF.verbose:
|
||||
root_logger.setLevel(logging.INFO)
|
||||
else:
|
||||
root_logger.setLevel(logging.WARNING)
|
||||
|
||||
formatter = logging.Formatter(CONF.log_format, CONF.log_date_format)
|
||||
|
||||
if CONF.use_syslog:
|
||||
try:
|
||||
facility = getattr(logging.handlers.SysLogHandler,
|
||||
CONF.syslog_log_facility)
|
||||
except AttributeError:
|
||||
raise ValueError(_("Invalid syslog facility"))
|
||||
|
||||
handler = logging.handlers.SysLogHandler(address='/dev/log',
|
||||
facility=facility)
|
||||
elif CONF.log_file:
|
||||
logfile = CONF.log_file
|
||||
if CONF.log_dir:
|
||||
logfile = os.path.join(CONF.log_dir, logfile)
|
||||
handler = logging.handlers.WatchedFileHandler(logfile)
|
||||
else:
|
||||
handler = logging.StreamHandler(sys.stdout)
|
||||
|
||||
handler.setFormatter(formatter)
|
||||
root_logger.addHandler(handler)
|
||||
|
||||
|
||||
def _get_deployment_flavor():
|
||||
"""
|
||||
Retrieve the paste_deploy.flavor config item, formatted appropriately
|
||||
for appending to the application name.
|
||||
"""
|
||||
flavor = CONF.paste_deploy.flavor
|
||||
return '' if not flavor else ('-' + flavor)
|
||||
|
||||
|
||||
def _get_paste_config_path():
|
||||
paste_suffix = '-paste.ini'
|
||||
conf_suffix = '.conf'
|
||||
if CONF.config_file:
|
||||
# Assume paste config is in a paste.ini file corresponding
|
||||
# to the last config file
|
||||
path = CONF.config_file[-1].replace(conf_suffix, paste_suffix)
|
||||
else:
|
||||
path = CONF.prog + '-paste.ini'
|
||||
return CONF.find_file(os.path.basename(path))
|
||||
|
||||
|
||||
def _get_deployment_config_file():
|
||||
"""
|
||||
Retrieve the deployment_config_file config item, formatted as an
|
||||
absolute pathname.
|
||||
"""
|
||||
path = CONF.paste_deploy.config_file
|
||||
if not path:
|
||||
path = _get_paste_config_path()
|
||||
if not path:
|
||||
msg = "Unable to locate paste config file for %s." % CONF.prog
|
||||
raise RuntimeError(msg)
|
||||
return os.path.abspath(path)
|
||||
|
||||
|
||||
def load_paste_app(app_name=None):
|
||||
"""
|
||||
Builds and returns a WSGI app from a paste config file.
|
||||
|
||||
We assume the last config file specified in the supplied ConfigOpts
|
||||
object is the paste config file.
|
||||
|
||||
:param app_name: name of the application to load
|
||||
|
||||
:raises RuntimeError when config file cannot be located or application
|
||||
cannot be loaded from config file
|
||||
"""
|
||||
if app_name is None:
|
||||
app_name = CONF.prog
|
||||
|
||||
# append the deployment flavor to the application name,
|
||||
# in order to identify the appropriate paste pipeline
|
||||
app_name += _get_deployment_flavor()
|
||||
|
||||
conf_file = _get_deployment_config_file()
|
||||
|
||||
try:
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.debug(_("Loading %(app_name)s from %(conf_file)s"),
|
||||
{'conf_file': conf_file, 'app_name': app_name})
|
||||
|
||||
app = deploy.loadapp("config:%s" % conf_file, name=app_name)
|
||||
|
||||
# Log the options used when starting if we're in debug mode...
|
||||
if CONF.debug:
|
||||
CONF.log_opt_values(logger, logging.DEBUG)
|
||||
|
||||
return app
|
||||
except (LookupError, ImportError), e:
|
||||
msg = _("Unable to load %(app_name)s from "
|
||||
"configuration file %(conf_file)s."
|
||||
"\nGot: %(e)r") % locals()
|
||||
logger.error(msg)
|
||||
raise RuntimeError(msg)
|
|
@ -1,116 +0,0 @@
|
|||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.from oslo.config import cfg
|
||||
|
||||
import anyjson
|
||||
from eventlet import patcher
|
||||
from glazierapi.db.models import Status, Session, Environment
|
||||
from glazierapi.db.session import get_session
|
||||
|
||||
amqp = patcher.import_patched('amqplib.client_0_8')
|
||||
|
||||
from glazierapi.openstack.common import service
|
||||
from glazierapi.openstack.common import log as logging
|
||||
from glazierapi.common import config
|
||||
|
||||
conf = config.CONF.reports
|
||||
rabbitmq = config.CONF.rabbitmq
|
||||
log = logging.getLogger(__name__)
|
||||
channel = None
|
||||
|
||||
|
||||
class TaskResultHandlerService(service.Service):
|
||||
def __init__(self, threads=1000):
|
||||
super(TaskResultHandlerService, self).__init__(threads)
|
||||
|
||||
def start(self):
|
||||
super(TaskResultHandlerService, self).start()
|
||||
self.tg.add_thread(self._handle_results)
|
||||
|
||||
def stop(self):
|
||||
super(TaskResultHandlerService, self).stop()
|
||||
|
||||
def _handle_results(self):
|
||||
connection = amqp.Connection('{0}:{1}'.
|
||||
format(rabbitmq.host, rabbitmq.port),
|
||||
virtual_host=rabbitmq.virtual_host,
|
||||
userid=rabbitmq.login,
|
||||
password=rabbitmq.password,
|
||||
ssl=rabbitmq.use_ssl, insist=True)
|
||||
ch = connection.channel()
|
||||
|
||||
def bind(exchange, queue):
|
||||
if not exchange:
|
||||
ch.exchange_declare(exchange, 'direct', durable=True,
|
||||
auto_delete=False)
|
||||
ch.queue_declare(queue, durable=True, auto_delete=False)
|
||||
if not exchange:
|
||||
ch.queue_bind(queue, exchange, queue)
|
||||
|
||||
bind(conf.results_exchange, conf.results_queue)
|
||||
bind(conf.reports_exchange, conf.reports_queue)
|
||||
|
||||
ch.basic_consume(conf.results_exchange, callback=handle_result)
|
||||
ch.basic_consume(conf.reports_exchange, callback=handle_report,
|
||||
no_ack=True)
|
||||
while ch.callbacks:
|
||||
ch.wait()
|
||||
|
||||
|
||||
def handle_report(msg):
|
||||
log.debug(_('Got report message from orchestration engine:\n{0}'.
|
||||
format(msg.body)))
|
||||
|
||||
params = anyjson.deserialize(msg.body)
|
||||
params['entity_id'] = params['id']
|
||||
del params['id']
|
||||
|
||||
status = Status()
|
||||
status.update(params)
|
||||
|
||||
session = get_session()
|
||||
#connect with session
|
||||
conf_session = session.query(Session).filter_by(
|
||||
**{'environment_id': status.environment_id,
|
||||
'state': 'deploying'}).first()
|
||||
status.session_id = conf_session.id
|
||||
|
||||
with session.begin():
|
||||
session.add(status)
|
||||
|
||||
|
||||
def handle_result(msg):
|
||||
log.debug(_('Got result message from '
|
||||
'orchestration engine:\n{0}'.format(msg.body)))
|
||||
|
||||
environment_result = anyjson.deserialize(msg.body)
|
||||
if 'deleted' in environment_result:
|
||||
log.debug(_('Result for environment {0} is dropped. '
|
||||
'Environment is deleted'.format(environment_result['id'])))
|
||||
|
||||
msg.channel.basic_ack(msg.delivery_tag)
|
||||
return
|
||||
|
||||
session = get_session()
|
||||
environment = session.query(Environment).get(environment_result['id'])
|
||||
|
||||
environment.description = environment_result
|
||||
environment.save(session)
|
||||
|
||||
#close session
|
||||
conf_session = session.query(Session).filter_by(
|
||||
**{'environment_id': environment.id, 'state': 'deploying'}).first()
|
||||
conf_session.state = 'deployed'
|
||||
conf_session.save(session)
|
||||
|
||||
msg.channel.basic_ack(msg.delivery_tag)
|
|
@ -1,19 +0,0 @@
|
|||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.from oslo.config import cfg
|
||||
|
||||
import uuid
|
||||
|
||||
|
||||
def generate_uuid():
|
||||
return str(uuid.uuid4()).replace('-', '')
|
|
@ -1,57 +0,0 @@
|
|||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from glazierapi.openstack.common import uuidutils
|
||||
|
||||
|
||||
class RequestContext(object):
|
||||
"""
|
||||
Stores information about the security context under which the user
|
||||
accesses the system, as well as additional request information.
|
||||
"""
|
||||
|
||||
def __init__(self, auth_token=None, user=None, tenant=None,
|
||||
roles=None, service_catalog=None, session=None):
|
||||
|
||||
self.auth_token = auth_token
|
||||
self.user = user
|
||||
self.tenant = tenant
|
||||
self.roles = roles or []
|
||||
self.request_id = uuidutils.generate_uuid()
|
||||
self.service_catalog = service_catalog
|
||||
self.session = session
|
||||
|
||||
def to_dict(self):
|
||||
# NOTE(ameade): These keys are named to correspond with the default
|
||||
# format string for logging the context in openstack common
|
||||
return {
|
||||
'request_id': self.request_id,
|
||||
|
||||
#NOTE(bcwaldon): openstack-common logging expects 'user'
|
||||
'user': self.user,
|
||||
'user_id': self.user,
|
||||
|
||||
#NOTE(bcwaldon): openstack-common logging expects 'tenant'
|
||||
'tenant': self.tenant,
|
||||
'tenant_id': self.tenant,
|
||||
'project_id': self.tenant,
|
||||
|
||||
'roles': self.roles,
|
||||
'auth_token': self.auth_token,
|
||||
'session': self.session
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, values):
|
||||
return cls(**values)
|
|
@ -1,26 +0,0 @@
|
|||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.from oslo.config import cfg
|
||||
|
||||
from oslo.config import cfg
|
||||
|
||||
sql_connection_opt = cfg.StrOpt('sql_connection',
|
||||
default='sqlite:///glazierapi.sqlite',
|
||||
secret=True,
|
||||
metavar='CONNECTION',
|
||||
help='A valid SQLAlchemy connection '
|
||||
'string for the metadata database. '
|
||||
'Default: %(default)s')
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opt(sql_connection_opt)
|
|
@ -1,4 +0,0 @@
|
|||
This is a database migration repository.
|
||||
|
||||
More information at
|
||||
http://code.google.com/p/sqlalchemy-migrate/
|
|
@ -1 +0,0 @@
|
|||
# template repository default module
|
|
@ -1,20 +0,0 @@
|
|||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.from oslo.config import cfg
|
||||
|
||||
|
||||
from migrate.versioning.shell import main
|
||||
|
||||
# This should probably be a console script entry point.
|
||||
if __name__ == '__main__':
|
||||
main(debug='False', repository='.')
|
|
@ -1,20 +0,0 @@
|
|||
[db_settings]
|
||||
# Used to identify which repository this database is versioned under.
|
||||
# You can use the name of your project.
|
||||
repository_id=Glazier Migrations
|
||||
|
||||
# The name of the database table used to track the schema version.
|
||||
# This name shouldn't already be used by your project.
|
||||
# If this is changed once a database is under version control, you'll need to
|
||||
# change the table name in each database too.
|
||||
version_table=migrate_version
|
||||
|
||||
# When committing a change script, Migrate will attempt to generate the
|
||||
# sql for all supported databases; normally, if one of them fails - probably
|
||||
# because you don't have that database installed - it is ignored and the
|
||||
# commit continues, perhaps ending successfully.
|
||||
# Databases in this list MUST compile successfully during a commit, or the
|
||||
# entire commit will fail. List the databases your application will actually
|
||||
# be using to ensure your updates to that database work properly.
|
||||
# This must be a list; example: ['glazier','sqlite']
|
||||
required_dbs=[]
|
|
@ -1,48 +0,0 @@
|
|||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.from oslo.config import cfg
|
||||
|
||||
from sqlalchemy.schema import MetaData, Table, Column, ForeignKey
|
||||
from sqlalchemy.types import String, Text, DateTime
|
||||
|
||||
|
||||
meta = MetaData()
|
||||
|
||||
Table('environment', meta,
|
||||
Column('id', String(32), primary_key=True),
|
||||
Column('name', String(255), nullable=False),
|
||||
Column('created', DateTime(), nullable=False),
|
||||
Column('updated', DateTime(), nullable=False),
|
||||
Column('tenant_id', String(32), nullable=False),
|
||||
Column('description', Text(), nullable=False),
|
||||
)
|
||||
|
||||
Table('service', meta,
|
||||
Column('id', String(32), primary_key=True),
|
||||
Column('name', String(255), nullable=False),
|
||||
Column('type', String(40), nullable=False),
|
||||
Column('environment_id', String(32), ForeignKey('environment.id')),
|
||||
Column('created', DateTime, nullable=False),
|
||||
Column('updated', DateTime, nullable=False),
|
||||
Column('description', Text(), nullable=False),
|
||||
)
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta.bind = migrate_engine
|
||||
meta.create_all()
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
meta.bind = migrate_engine
|
||||
meta.drop_all()
|
|
@ -1,39 +0,0 @@
|
|||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.from oslo.config import cfg
|
||||
|
||||
from sqlalchemy.schema import MetaData, Table, Column, ForeignKey
|
||||
from sqlalchemy.types import String, Text, DateTime
|
||||
|
||||
meta = MetaData()
|
||||
|
||||
session = Table('session', meta,
|
||||
Column('id', String(32), primary_key=True),
|
||||
Column('environment_id', String(32),
|
||||
ForeignKey('environment.id')),
|
||||
Column('created', DateTime, nullable=False),
|
||||
Column('updated', DateTime, nullable=False),
|
||||
Column('user_id', String(32), nullable=False),
|
||||
Column('state', Text(), nullable=False),
|
||||
)
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta.bind = migrate_engine
|
||||
meta.reflect()
|
||||
session.create()
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
meta.bind = migrate_engine
|
||||
session.drop()
|
|
@ -1,40 +0,0 @@
|
|||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.from oslo.config import cfg
|
||||
|
||||
from sqlalchemy.schema import MetaData, Table, Column, ForeignKey
|
||||
from sqlalchemy.types import String, Text, DateTime
|
||||
|
||||
meta = MetaData()
|
||||
|
||||
status = Table('status', meta,
|
||||
Column('id', String(32), primary_key=True),
|
||||
Column('created', DateTime, nullable=False),
|
||||
Column('updated', DateTime, nullable=False),
|
||||
Column('entity', String(10), nullable=False),
|
||||
Column('environment_id', String(32),
|
||||
ForeignKey('environment.id')),
|
||||
Column('session_id', String(32), ForeignKey('session.id')),
|
||||
Column('text', Text(), nullable=False),
|
||||
)
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta.bind = migrate_engine
|
||||
meta.reflect()
|
||||
status.create()
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
meta.bind = migrate_engine
|
||||
status.drop()
|
|
@ -1,31 +0,0 @@
|
|||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.from oslo.config import cfg
|
||||
|
||||
from sqlalchemy.schema import MetaData, Table, Column
|
||||
from sqlalchemy.types import Text
|
||||
|
||||
meta = MetaData()
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta.bind = migrate_engine
|
||||
session = Table('session', meta, autoload=True)
|
||||
description = Column('description', Text(), nullable=True, default='{}')
|
||||
description.create(session)
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
meta.bind = migrate_engine
|
||||
session = Table('session', meta, autoload=True)
|
||||
session.c.description.drop()
|
|
@ -1,42 +0,0 @@
|
|||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.from oslo.config import cfg
|
||||
|
||||
from sqlalchemy.schema import MetaData, Table, Column, ForeignKey
|
||||
from sqlalchemy.types import String, Text, DateTime
|
||||
|
||||
|
||||
meta = MetaData()
|
||||
|
||||
service = Table('service', meta,
|
||||
Column('id', String(32), primary_key=True),
|
||||
Column('name', String(255), nullable=False),
|
||||
Column('type', String(40), nullable=False),
|
||||
Column('environment_id', String(32),
|
||||
ForeignKey('environment.id')),
|
||||
Column('created', DateTime, nullable=False),
|
||||
Column('updated', DateTime, nullable=False),
|
||||
Column('description', Text(), nullable=False),
|
||||
)
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta.bind = migrate_engine
|
||||
meta.reflect()
|
||||
service.drop()
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
meta.bind = migrate_engine
|
||||
meta.reflect()
|
||||
service.create()
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue