SQL Server Cluster workflow

Change-Id: I1287f35d756f2ea3937e7711872ad8bd073a0c87
This commit is contained in:
Stan Lagun 2013-08-02 17:09:59 +04:00
parent 0c1be89f2f
commit ab7a9305ce
10 changed files with 441 additions and 9 deletions

View File

@ -0,0 +1,18 @@
{
"Commands": [
{
"Name": "New-SqlServerSystemAccount",
"Arguments": {
"UserName": "$domainAdminAccountName",
"SQLServiceUserPassword": "$sqlServiceAccountPassword",
"UserPassword": "$domainAdminAccountPassword",
"DomainName": "$domainName",
"SQLServiceUserName": "$sqlServiceAccountName"
}
}
],
"Scripts": [
"SW1wb3J0LU1vZHVsZSBDb3JlRnVuY3Rpb25zIC1Gb3JjZQ==",
"CmZ1bmN0aW9uIE5ldy1TcWxTZXJ2ZXJTeXN0ZW1BY2NvdW50IHsKICAgIHBhcmFtICgKICAgICAgICAjIChSRVFVSVJFRCkgRG9tYWluIE5hbWUKICAgICAgICBbUGFyYW1ldGVyKE1hbmRhdG9yeT0kdHJ1ZSldCiAgICAgICAgW1N0cmluZ10gJERvbWFpbk5hbWUsCgogICAgICAgICMgKFJFUVVJUkVEKSBVc2VyIG5hbWUgd2hvIGhhcyBwZXJtaXNzaW9ucyB0byBjcmVhdGUgYW5kIG1vZGlmeSB1c2VyUGFzc3dvcmQKICAgICAgICAjIFVzdWFsbHkgdGhpcyBpcyB0aGUgZG9tYWluIGFkbWluaXN0cmF0b3IgJyRkb21haW5OYW1lXEFkbWluaXN0cmF0b3InIGFjY291bnQKICAgICAgICBbUGFyYW1ldGVyKE1hbmRhdG9yeT0kdHJ1ZSldCiAgICAgICAgW1N0cmluZ10gJFVzZXJOYW1lLAoKICAgICAgICAjIChSRVFVSVJFRCkgUGFzc3dvcmQgZm9yIHRoYXQgdXNlcgogICAgICAgIFtQYXJhbWV0ZXIoTWFuZGF0b3J5PSR0cnVlKV0KICAgICAgICBbU3RyaW5nXSAkVXNlclBhc3N3b3JkLAoKICAgICAgICAjIChSRVFVSVJFRCkgVXNlciBuYW1lIGZvciBhIG5ldyBhY2NvdW50IHRoYXQgd2lsbCBiZSB1c2VkIHRvIHJ1biBTUUwgU2VydmVyCiAgICAgICAgW1BhcmFtZXRlcihNYW5kYXRvcnk9JHRydWUpXQogICAgICAgIFtTdHJpbmddICRTUUxTZXJ2aWNlVXNlck5hbWUsCgogICAgICAgICMgKFJFUVVJUkVEKSBQYXNzd29yZCBmb3IgdGhhdCB1c2VyCiAgICAgICAgW1BhcmFtZXRlcihNYW5kYXRvcnk9JHRydWUpXQogICAgICAgIFtTdHJpbmddICRTUUxTZXJ2aWNlVXNlclBhc3N3b3JkCiAgICApCn0K"
]
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -161,7 +161,7 @@
<success>
<report entity="unit">
<parameter name="id"><select path="id" source="unit"/></parameter>
<parameter name="text">Unit <select path="state.hostname" source="unit"/> (<select path="name" source="unit"/>) has leaved domain <select path="state.domain"/></parameter>
<parameter name="text">Unit <select path="state.hostname" source="unit"/> (<select path="name" source="unit"/>) has left domain <select path="state.domain"/></parameter>
</report>
<set path="state.domain"><null/></set>
</success>
@ -176,9 +176,8 @@
<set path="#service">
<select path="::"/>
</set>
<rule>
<rule desc="Domain controller exists with the assigned DNS IP">
<parameter name="match">/$.services[?(@.type == 'activeDirectory' and @.domain == '<select path="domain"/>' and @.state.primaryDcIp)]</parameter>
<parameter name="desc">Domain controller exists with the assigned DNS IP</parameter>
<send-command template="JoinDomain">
<parameter name="unit">
<select path="id" source="unit"/>
@ -197,7 +196,9 @@
<mapping name="dnsIp">
<select path="state.primaryDcIp"/>
</mapping>
<mapping name="domainUser">Administrator</mapping>
<mapping name="domainUser">
<select path="adminAccountName" default="Administrator"/>
</mapping>
<mapping name="ouPath"></mapping>
</map>
</parameter>

View File

@ -0,0 +1,292 @@
<workflow>
<rule match="$.services[?(@.type == 'msSqlClusterServer' and @.domain)].units[*]"
desc="Units of SQL Server Cluster services which are part of the domain">
<set path="domain">
<select path="::domain"/>
</set>
</rule>
<rule match="$.services[?(@.type == 'msSqlClusterServer')].units[?(@.state.hostname and @.state.osImageName and not @.state.instanceName)]"
desc="Units of SQL Server Cluster services having hostname and image names assigned but without instances">
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Creating instance <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
<update-cf-stack template="Windows">
<parameter name="mappings">
<map>
<mapping name="instanceName"><select path="state.hostname"/></mapping>
<mapping name="userData">
<prepare-user-data>
<parameter name="hostname"><select path="state.hostname"/></parameter>
<parameter name="unit"><select path="id"/></parameter>
<parameter name="service"><select path="::id"/></parameter>
</prepare-user-data>
</mapping>
</map>
</parameter>
<parameter name="arguments">
<map>
<argument name="InstanceType"><select path="::flavor" default="m1.medium"/></argument>
<argument name="ImageName"><select path="state.osImageName"/></argument>
<argument name="AvailabilityZone"><select path="::availabilityZone" default="nova"/></argument>
</map>
</parameter>
<success>
<set path="state.instanceName"><select path="name"/></set>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Instance <select path="state.hostname"/> (<select path="name"/>) created</parameter>
</report>
</success>
</update-cf-stack>
</rule>
<rule match="$.services[?(@.type == 'msSqlClusterServer' and @.domain and not @.domainAdminUserName and not @.domainAdminPassword)]"
desc="SQL Server Cluster service instance with domain configured but without admin account name/password">
<set path="#service">
<select/>
</set>
<rule desc="Domain controller exists with the assigned DNS IP">
<parameter name="match">/$.services[?(@.type == 'activeDirectory' and @.domain == '<select path="domain"/>')]</parameter>
<set path="domainAdminUserName" target="service"><select path="adminAccountName" default="Administrator"/></set>
<set path="domainAdminPassword" target="service"><select path="adminPassword"/></set>
</rule>
</rule>
<rule match="$.services[?(@.type == 'msSqlClusterServer' and @.adminPassword and @.adminPassword != @.state.adminPassword)].units[?(@.state.instanceName)]"
desc="Units of SQL Server Cluster services which have got an instance deployed but has not got a correct admin password">
<send-command template="SetPassword">
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="adminPassword">
<select path="::adminPassword"/>
</mapping>
</map>
</parameter>
<success>
<set path="::state.adminPassword">
<select path="::adminPassword"/>
</set>
</success>
</send-command>
</rule>
<rule match="$.services[?(@.type == 'msSqlClusterServer')].units[?(@.state.domain and not @.state.failoverClusterPrerequisitesInstalled)]"
desc="Units of SQL Server Cluster services that are already joined AD domain">
<send-command template="SqlServerCluster/FailoverClusterPrerequisites">
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<success>
<set path="state.failoverClusterPrerequisitesInstalled"><true/></set>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Failover cluster prerequisites installed on unit <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
</success>
</send-command>
</rule>
<rule match="$.services[?(@.type == 'msSqlClusterServer' and not @.state.failoverClusterCreated)].units[?(@.state.failoverClusterPrerequisitesInstalled)]" limit="1"
desc="First unit of SQL Server Cluster services that is already has failover cluster prerequisites installed">
<send-command template="SqlServerCluster/FailoverCluster">
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="clusterName">
<select path="::clusterName"/>
</mapping>
<mapping name="clusterNodes">
<select-all path=":$[*].state.hostname"/>
</mapping>
<mapping name="domainAdminAccountName">
<select path="::domainAdminUserName"/>
</mapping>
<mapping name="domainAdminAccountPassword">
<select path="::domainAdminPassword"/>
</mapping>
<mapping name="clusterIP">
<select path="::clusterIP"/>
</mapping>
<mapping name="sqlServiceAccountName">
<select path="::sqlServiceUserName"/>
</mapping>
<mapping name="sqlServiceAccountPassword">
<select path="::sqlServicePassword"/>
</mapping>
<mapping name="domainName">
<select path="state.domain"/>
</mapping>
</map>
</parameter>
<success>
<set path="::state.failoverClusterCreated"><true/></set>
<report entity="service">
<parameter name="id"><select path="::id"/></parameter>
<parameter name="text">Failover cluster created for SQL Server Cluster service (<select path="::name"/>)</parameter>
</report>
</success>
</send-command>
</rule>
<rule match="$.services[?(@.type == 'msSqlClusterServer' and @.state.failoverClusterCreated and not @.state.agEnvironmentConfigured)].units[*]" limit="1"
desc="First unit of SQL Server Cluster services that is already has failover cluster created">
<send-command template="SqlServerCluster/ConfigureEnvironmentForAOAG">
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="domainAdminAccountName">
<select path="::domainAdminUserName"/>
</mapping>
<mapping name="domainAdminAccountPassword">
<select path="::domainAdminPassword"/>
</mapping>
<mapping name="sqlServiceAccountName">
<select path="::sqlServiceUserName"/>
</mapping>
<mapping name="sqlServiceAccountPassword">
<select path="::sqlServicePassword"/>
</mapping>
<mapping name="domainName">
<select path="state.domain"/>
</mapping>
</map>
</parameter>
<success>
<set path="::state.agEnvironmentConfigured"><true/></set>
<report entity="service">
<parameter name="id"><select path="::id"/></parameter>
<parameter name="text">Environment for AlwaysOn Availability Group of SQL Server Cluster service (<select path="::name"/>) configured</parameter>
</report>
</success>
</send-command>
</rule>
<rule match="$.services[?(@.type == 'msSqlClusterServer' and @.state.agEnvironmentConfigured)].units[?(@.state.failoverClusterPrerequisitesInstalled and not @.state.sqlServerInstalled)]"
desc="All units of SQL Server Cluster services that is already has environment configured">
<send-command template="SqlServerCluster/InstallSqlServerForAOAG">
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="sqlServiceAccountName">
<select path="::sqlServiceUserName"/>
</mapping>
<mapping name="sqlServiceAccountPassword">
<select path="::sqlServicePassword"/>
</mapping>
<mapping name="domainName">
<select path="state.domain"/>
</mapping>
</map>
</parameter>
<success>
<set path="state.sqlServerInstalled"><true/></set>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">SQL Server installed on unit <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
</success>
</send-command>
</rule>
<rule match="$.services[?(@.type == 'msSqlClusterServer')].units[?(@.state.sqlServerInstalled and not @.state.primaryReplicaInitialized)]"
desc="All units of SQL Server Cluster services that has SQL Server installed">
<send-command template="SqlServerCluster/InitializeAOAGPrimaryReplica">
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="groupName">
<select path="::agGroupName"/>
</mapping>
<mapping name="nodeList">
<select-all path=":$[*].state.hostname"/>
</mapping>
<mapping name="primaryNode">
<select-single path=":$[?(@.isMaster)].state.hostname"/>
</mapping>
<mapping name="syncModeNodeList">
<select-all path=":$[?(@.isSync)].state.hostname"/>
</mapping>
<mapping name="listenerIP">
<select path="::agListenerIP"/>
</mapping>
<mapping name="listenerName">
<select path="::agListenerName"/>
</mapping>
<mapping name="databaseList">
<select path="::databases"/>
</mapping>
</map>
</parameter>
<success>
<set path="state.primaryReplicaInitialized"><true/></set>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Primary replica for SQL Server AG initialized for <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
</success>
</send-command>
</rule>
<rule match="$.services[?(@.type == 'msSqlClusterServer')].units[?(@.state.primaryReplicaInitialized and not @.state.secondaryReplicaInitialized)]"
desc="All units of SQL Server Cluster services that has primary replica initialized">
<send-command template="SqlServerCluster/InitializeAOAGSecondaryReplica">
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="nodeList">
<select-all path=":$[*].state.hostname"/>
</mapping>
<mapping name="primaryNode">
<select-single path=":$[?(@.isMaster)].state.hostname"/>
</mapping>
</map>
</parameter>
<success>
<set path="state.secondaryReplicaInitialized"><true/></set>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Secondary replica for SQL Server AG initialized for <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
</success>
</send-command>
</rule>
</workflow>

View File

@ -7,7 +7,7 @@
</rule>
<rule match="$.services[?(@.type == 'msSqlServer')].units[?(@.state.hostname and @.state.osImageName and not @.state.instanceName)]"
desc="Units of SQLServer services having hostname and image names assigned but without instances">
desc="Units of SQL Server services having hostname and image names assigned but without instances">
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Creating instance <select path="state.hostname"/> (<select path="name"/>)</parameter>
@ -44,7 +44,7 @@
</rule>
<rule match="$.services[?(@.type == 'msSqlServer' and @.adminPassword and @.adminPassword != @.state.adminPassword)].units[?(@.state.instanceName)]"
desc="Units of SQLServer services which have got an instance deployed but has not got a correct admin password">
desc="Units of SQL Server services which have got an instance deployed but has not got a correct admin password">
<send-command template="SetPassword">
<parameter name="unit">
<select path="id"/>
@ -69,7 +69,7 @@
<rule match="$.services[?(@.type == 'msSqlServer')].units[?(@.state.instanceName and not @.state.msSqlServerInstalled)]"
desc="Units of SqlServer services which have got an instance deployed but have not got an SQL Server installed">
desc="Units of SQL Server services which have got an instance deployed but have not got an SQL Server installed">
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Creating MS SQL Server on unit <select path="state.hostname"/> (<select path="name"/>)</parameter>

View File

@ -151,8 +151,6 @@ class Workflow(object):
@staticmethod
def _rule_func(match, context, body, engine, limit=0, name=None, desc=None,
**kwargs):
position = context['__dataSource_currentPosition'] or []
position, match = Workflow._get_relative_position(match, context)
if not desc:
desc = match
@ -183,6 +181,19 @@ class Workflow(object):
log.debug("Running empty handler for rule '{0}'".format(desc))
engine.evaluate_content(empty_handler, context)
@staticmethod
def _select_all_func(context, path='', source=None, limit=0, **kwargs):
if not source:
position, path = Workflow._get_relative_position(path, context)
source = Workflow._get_path(context['/dataSource'], position)
result = jsonpath.jsonpath(source, path) or []
return result if not limit else result[:limit]
@staticmethod
def _select_single_func(context, path='', source=None, **kwargs):
result = Workflow._select_all_func(context, path, source, **kwargs)
return result[0] if len(result) >= 1 else None
@staticmethod
def _workflow_func(context, body, engine, **kwargs):
context['/hasSideEffects'] = False
@ -204,3 +215,9 @@ xml_code_engine.XmlCodeEngine.register_function(
xml_code_engine.XmlCodeEngine.register_function(
Workflow._select_func, 'select')
xml_code_engine.XmlCodeEngine.register_function(
Workflow._select_all_func, 'select-all')
xml_code_engine.XmlCodeEngine.register_function(
Workflow._select_single_func, 'select-single')