Замена ключевого компонента системы никогда не бывает безболезненным: всегда приходится идти на компромиссы, чем-то жертвовать, что-то доделывать. Принимаемые решения всегда балансируют между двумя противоположными целями: сделать правильно и добиться обратной совместимости, чтобы минимизировать потери времени и не навредить стабильности продукта. В итоге новый компонент частично обретает черты старого, где-то вынужденно повторяет его ошибки. Это неизбежная плата за возможность наиболее безболезненным образом исправить некоторый фатальный недостаток старого компонента, из-за которого и был затеян весь переход. Не стал исключением и наш Windows Provisioning Engine, о котором я начал рассказывать в прошлый раз. Если сравнить его с Microsoft Provisioning System, то можно обнаружить много общего.
До
Изначально в качестве системы управления мы использовали Microsoft Provisioning System – это решение компании Microsoft, как раз предназначенное для управления инфраструктурой поставщиков услуг. Если описывать её упрощённо, то эта система состояла из серверного компонента, принимающего запросы от контрольной панели, и набора провайдеров, каждый из которых реализовывал управляющие процедуры из какой-то конкретной предметной области. Так, например, провайдер Active Directory покрывал все аспекты управления организационными единицами, пользователями, группами и прочими объектами каталога. Система поставлялась с большим количеством готовых провайдеров и позволяла расширять их набор за счёт своих. SDK MPS`а первых версий позволял писать провайдеры исключительно на C++, в дальнейшем появилась возможность использовать .NET.
Серверный компонент, принимающий запросы, был реализован как DCOM сервер. В дальнейшем над ним появилась надстройка в виде Web-сервисов, но мы её никогда не использовали. Сам сервер не представлял из себя ничего примечательного. По сути это был DCOM объект, который помимо некоторого количества вспомогательных методов реализовывал метод SubmitRequest, именно он и позволял управлять всей инфраструктурой. Этот метод принимал в качестве строкового аргумента запрос, написанный на специальном языке. Именно этот язык и был самой примечательной частью всей системы. Он базировался на XML`е, но при этом содержал ряд характерных империческим языкам управляющих конструкций, таких как: цикл, ветвление, обработка исключений и так далее. Ниже приведён пример такого запроса, чтобы было легче себе представить, что это такое (обратите внимание на замечательный тэги foreach – вы никогда не видели цикла в XML – я прежде тоже
):
Отдельная инструкция, обозначающаяся тегом execute, отвечает непосредственно за вызов какой-либо управляющей процедуры из того или иного провайдера. Таким образом, чтобы реализовать сценарий управления, контрольной панели необходимо правильно сформировать подобный запрос и передать его на исполнение серверу MPS. Причём часть логики сценария, вроде обработки ошибок, может содержаться непосредственно в самом запросе.
Функции этого языка не ограничивались лишь запросами к системе. Он использовался и в качестве языка сценариев для написания целых провайдеров наряду с такими компилируемыми языками как C++ и C#. И хотя возможности именно этих провайдеров (написанных на скриптовом языке) были ограниченны функционалом предоставляемым системой и её компонентами (в частности другими провайдерами), их главный плюс был в том, что они всегда поставлялись в открытом виде – это позволяло при необходимости вносить исправления прямо на месте, для быстрого решения проблем на развёрнутых инфраструктурах поставщиков услуг.
После
Как я уже говорил, у MPS есть один фатальный недостаток: её разработка и поддержка прекращена. Поэтому, когда в один прекрасный момент перед нами замаячила перспектива разработки собственной системы управления инфраструктурой, мы столкнулись с двумя принципиальными проблемами:
Реализованная поддержка языка MPS`а была действительно очень ограниченная, и скриптовые провайдеры были обречены. Но выбрасывать работающий код на компилируемом языке было бы большой глупостью, тем более что в случае провайдеров, написанных на языке C#, мы никогда не использовали MPS SDK напрямую. У нас была небольшая библиотека, которая полностью инкапсулировала все аспекты работы с MPS и таким образом изолировала провайдера от особенностей системы, в рамках которой ему предстояло функционировать. Поэтому, чтобы добиться полной совместимости нашей новой системой управления с нашими же провайдерами, написанными на языке C# для MPS`а, было достаточно просто переписать данную библиотеку.
Получившийся в итоге Windows Provisioning Engine представляет собой Web-сервис без состояния, реализующий единственный метод executeRequest. Запрос, который может быть передан этому методу на исполнение, формируется на урезанной версии языка MPS`а с возможностью использования лишь ограниченного набора управляющих конструкций. В качестве основных модулей расширения функциональности системы используются провайдеры, написанные на языке PowerShell. В дополнение к ним существует некоторое количество наших .NET провайдеров, перенесённых из MPS`а благодаря специальной библиотеке-прослойке. Отсутствие у Web-сервиса состояния позволяет решать задачу кластеризации системы управления без лишних затрат.
До
Изначально в качестве системы управления мы использовали Microsoft Provisioning System – это решение компании Microsoft, как раз предназначенное для управления инфраструктурой поставщиков услуг. Если описывать её упрощённо, то эта система состояла из серверного компонента, принимающего запросы от контрольной панели, и набора провайдеров, каждый из которых реализовывал управляющие процедуры из какой-то конкретной предметной области. Так, например, провайдер Active Directory покрывал все аспекты управления организационными единицами, пользователями, группами и прочими объектами каталога. Система поставлялась с большим количеством готовых провайдеров и позволяла расширять их набор за счёт своих. SDK MPS`а первых версий позволял писать провайдеры исключительно на C++, в дальнейшем появилась возможность использовать .NET.
Серверный компонент, принимающий запросы, был реализован как DCOM сервер. В дальнейшем над ним появилась надстройка в виде Web-сервисов, но мы её никогда не использовали. Сам сервер не представлял из себя ничего примечательного. По сути это был DCOM объект, который помимо некоторого количества вспомогательных методов реализовывал метод SubmitRequest, именно он и позволял управлять всей инфраструктурой. Этот метод принимал в качестве строкового аргумента запрос, написанный на специальном языке. Именно этот язык и был самой примечательной частью всей системы. Он базировался на XML`е, но при этом содержал ряд характерных империческим языкам управляющих конструкций, таких как: цикл, ветвление, обработка исключений и так далее. Ниже приведён пример такого запроса, чтобы было легче себе представить, что это такое (обратите внимание на замечательный тэги foreach – вы никогда не видели цикла в XML – я прежде тоже
<request>
<data>
<organizations>
<organization name="tailspintoys.com" type="primary">
<user name="joe"/>
<user name="nancy"/>
</organization>
<organization name="wideworldimporters.com" type="primary">
<user name="fred"/>
</organization>
<organization name="fourthcoffee.com" type="secondary">
</organization>
<organization name="adventure-works.com" type="secondary">
</organization>
</organizations>
</data>
<procedure>
<execute namespace="Test Namespace" procedure="Write Request">
<forEach
name="organization"
root="data"
path="organizations/organization"/>
<forEach
name="user"
root="organization"
path="user"
ifNull="skip"/>
<before source="organization" destination="executeData">
<xsl:template match="organization[@type='primary']">
<primaryOrg>
<xsl:value-of select="@name"/>
</primaryOrg>
</xsl:template>
<xsl:template match="organization[@type='secondary']">
<secondaryOrg>
<xsl:value-of select="@name"/>
</secondaryOrg>
</xsl:template>
</before>
<after
source="executeData"
destination="data"
destinationPath="orgSignup"
mode="merge"/>
</execute>
</procedure>
</request>
<data>
<organizations>
<organization name="tailspintoys.com" type="primary">
<user name="joe"/>
<user name="nancy"/>
</organization>
<organization name="wideworldimporters.com" type="primary">
<user name="fred"/>
</organization>
<organization name="fourthcoffee.com" type="secondary">
</organization>
<organization name="adventure-works.com" type="secondary">
</organization>
</organizations>
</data>
<procedure>
<execute namespace="Test Namespace" procedure="Write Request">
<forEach
name="organization"
root="data"
path="organizations/organization"/>
<forEach
name="user"
root="organization"
path="user"
ifNull="skip"/>
<before source="organization" destination="executeData">
<xsl:template match="organization[@type='primary']">
<primaryOrg>
<xsl:value-of select="@name"/>
</primaryOrg>
</xsl:template>
<xsl:template match="organization[@type='secondary']">
<secondaryOrg>
<xsl:value-of select="@name"/>
</secondaryOrg>
</xsl:template>
</before>
<after
source="executeData"
destination="data"
destinationPath="orgSignup"
mode="merge"/>
</execute>
</procedure>
</request>
Отдельная инструкция, обозначающаяся тегом execute, отвечает непосредственно за вызов какой-либо управляющей процедуры из того или иного провайдера. Таким образом, чтобы реализовать сценарий управления, контрольной панели необходимо правильно сформировать подобный запрос и передать его на исполнение серверу MPS. Причём часть логики сценария, вроде обработки ошибок, может содержаться непосредственно в самом запросе.
Функции этого языка не ограничивались лишь запросами к системе. Он использовался и в качестве языка сценариев для написания целых провайдеров наряду с такими компилируемыми языками как C++ и C#. И хотя возможности именно этих провайдеров (написанных на скриптовом языке) были ограниченны функционалом предоставляемым системой и её компонентами (в частности другими провайдерами), их главный плюс был в том, что они всегда поставлялись в открытом виде – это позволяло при необходимости вносить исправления прямо на месте, для быстрого решения проблем на развёрнутых инфраструктурах поставщиков услуг.
После
Как я уже говорил, у MPS есть один фатальный недостаток: её разработка и поддержка прекращена. Поэтому, когда в один прекрасный момент перед нами замаячила перспектива разработки собственной системы управления инфраструктурой, мы столкнулись с двумя принципиальными проблемами:
- Что взять за основу языка сценариев для разработки провайдеров?
- Как быть с наследием MPS`а, активно использующимся контрольной панелью?
- Запросы на скриптовом языке MPS`а, формируемые контрольной панелью и отправляемые системе управления инфраструктурой.
- Собственные провайдеры, написанные на скриптовом языке MPS`а.
- Собственные провайдеры, написанные на компилируемых языках C# и C++.
Реализованная поддержка языка MPS`а была действительно очень ограниченная, и скриптовые провайдеры были обречены. Но выбрасывать работающий код на компилируемом языке было бы большой глупостью, тем более что в случае провайдеров, написанных на языке C#, мы никогда не использовали MPS SDK напрямую. У нас была небольшая библиотека, которая полностью инкапсулировала все аспекты работы с MPS и таким образом изолировала провайдера от особенностей системы, в рамках которой ему предстояло функционировать. Поэтому, чтобы добиться полной совместимости нашей новой системой управления с нашими же провайдерами, написанными на языке C# для MPS`а, было достаточно просто переписать данную библиотеку.
Получившийся в итоге Windows Provisioning Engine представляет собой Web-сервис без состояния, реализующий единственный метод executeRequest. Запрос, который может быть передан этому методу на исполнение, формируется на урезанной версии языка MPS`а с возможностью использования лишь ограниченного набора управляющих конструкций. В качестве основных модулей расширения функциональности системы используются провайдеры, написанные на языке PowerShell. В дополнение к ним существует некоторое количество наших .NET провайдеров, перенесённых из MPS`а благодаря специальной библиотеке-прослойке. Отсутствие у Web-сервиса состояния позволяет решать задачу кластеризации системы управления без лишних затрат.
Продолжение следует...
5 комментариев:
//обратите внимание на замечательный тэги foreach – вы никогда не видели цикла в XML – я прежде тоже
В XSLT же есть foreach http://www.w3schools.com/xsl/xsl_for_each.asp
Ну от XSLT ты этого ожидаешь - суть у него такая. А тут именно декларация запроса в XML`е и вдруг управляющие конструкции вроде forEach, try, catch и прочего. Вообще там очень жуткая мешанина, которая местами включает даже XSLT. Но последнее весьма ограничено.
Но вообще спасибо за замечание - буду ещё внимательнее вычитывать текст в следующий раз.
Добрый день.
А продолжение будет?
Извиняюсь, похоже забыл обновить ссылки на странице. Окончание серии вот здесь: http://mrnone.blogspot.ru/2012/11/powershell.html
Благодарю.
Отправить комментарий