Mostrando entradas con la etiqueta Despliegue. Mostrar todas las entradas
Mostrando entradas con la etiqueta Despliegue. Mostrar todas las entradas

Desplegar Solución de forma no global

Cuando preparamos paquetes de solución para nuestras aplicaciones de SharePoint, la forma natural en la que Visual Studio nos prepara dichos paquetes, es para hacer un despliegue Global. ¿Qué quiere decir un despliegue global? Quiere decir que el paquete se va a desplegar para estar disponible en todas las Web Applications que están en la granja.

Desde el punto de vista de soluciones de SharePoint, esta es la forma normal, para poder reutilizar soluciones y para poder usar características entre Web Applications. Pero no siempre queremos que sea así, y hay veces que tenemos la necesidad de desplegar una solución de forma única para una determinada Web Application en concreto.

Vamos con un ejemplo. Si montamos un Timer Job para que se despliegue de forma global, basta con generar la clase del Job, una Feature con la activación del mismo, y un paquete de solución por defecto que incluya dicha feature:

image

image

Y desplegamos desde Visual Studio:

image

Y ahora si comprobamos desde la Administración Central cómo ha quedado desplegado nuestro paquete, podremos ver que se ha desplegado de forma Global:

image

Ahora vamos a generar un paquete diferente para que se despliegue a la que nosotros queremos.

Para ello hay que modificar desde Visual Studio el paquete, teniendo que prescindir del Wizard y haciendo la edición manual mediante XML. Básicamente se trata de añadir una entrada de Safe Control a la DLL que se genera en nuestro proyecto de SharePoint. Si tuvieramos más componentes propios y / o de terceros, esos se quedarían como están. Sólo hay que añadir el Safe Control al Assembly del proyecto de SharePoint.

Para ello, lo primero de todo, localizamos el paquete, y desde la pestaña de Manifest, hacemos clic en la parte inferior en Edit Options, donde podemos decir que queremos abrir el diseñador en modo XML:

image

image

Una vez confirmada la advertencia, editamos en el modo XML:

image

Y veremos algo similar a esto:

image

Hay que añadir por lo tanto una etiqueta de Safe Control al Assembly del proyecto, de forma que quedaría algo como la siguiente:

image

Ahora si desplegamos nuestro paquete, y revisamos desde la Administración Central el estado de nuestra solución, veremos que ya está desplegada para una Web Application en concreto:

image

Introducción a los despliegues automatizados. Parte II: Despliegue remoto

Si en el post anterior vimos cómo configurar el entorno de TFS y el Servidor de SharePoint para permitir la ejecución remota de scripts de PowerShell, ahora vamos a ver cómo realizar en un siguiente paso dentro de una Build de TFS el despliegue automatizado.

La idea es la siguiente: generar un paquete, o paquetes en la Build, y llamar a un script “maestro” de PowerShell que se encargue de lanzar una llamada al script de despliegue de dichos paquetes. Gráficamente, esto es lo que queremos conseguir:

image

El Script Maestro, va a ser genérico, por lo tanto habrá unas cuantas reglas que se deberán cumplir, como por ejemplo, que el nombre del script de despliegue sea “Install.ps1”, aunque podremos cambiarlo.

El script de deploy, que se desplegará con el resto del paquete en la máquina de SharePoint, podrá tener lo necesario para ejecutar el despliegue.

La generación de paquete es importante, ya que si se sigue un cierto orden, este mecanismo de despliegue puede ser válido para los proyectos que se desee. Un ejemplo de un paquete generado por la Build es el siguiente:

image

En este paquete por ejemplo se incluye una documentación, el paquete de solución WSP, un archivo de configuración del que se alimenta el script de “Install.ps1”, y un script común con funciones genéricas.

En Visual Studio, se podría organizar el proyecto de la siguiente forma:

image

No voy a entrar a detallar cómo organizar un proyecto, porque cada uno tendrá su propia metodología o estará mas acostumbrado a realizarlo de otra forma. De cualquier manera, la idea del despliegue automatizado sigue siendo igual de válida.

Bien, lo que haremos será generar una nueva plantilla para Build de TFS:

image

Dentro de la secuencia principal, vamos a entrar en la de Run On Agent, para añadir dos secuencias más:

image

Después de la secuencia de Try, Compile and Test, vamos a añadir la secuencia de generar el paquete, y posteriormente la de lanzar el despliegue automatizado, similar a la siguiente:

image

No voy a describir entero el proceso de crear el paquete de despliegue, pero el objetivo es generar una carpeta de deploy, que contenga lo necesario para el despliegue, como vimos en el dibujo anterior. Un ejemplo podría ser:

image

Yo recomiendo generar tantas secuencias como sean necesarias a fin de que podamos hacer seguimiento de cada una de forma cómoda.

Es importante que de las secuencias anteriores, creemos el directorio donde se dejarán los ficheros. La variable que creemos para generar el directorio debería ser similar a la siguiente:

image

Es importante que indiquemos a la Build que queremos generar los paquetes WSP. Para ello, hay que indicar en su atributo MSBuild Arguments lo siguiente:

image

El resto de ficheros basta copiarlos usando las secuencias de FindMatchingItems y la de InvokeProcess llamando a “xcopy.exe” para copiar al “PackageFolder” que se definió en la variable anterior.

Ahora, para configurar la secuencia de despliegue automático, hay que indicar en qué ruta vamos a dejar el script maestro de instalación. Por ejemplo de la siguiente manera:

image

Dentro de la secuencia tendremos un proceso de invocación como el siguiente (InvokeProcess):

image

Con una configuración similar a la siguiente:

image

De tal forma que se llame al script maestro, indicando la máquina donde se va a realizar el despliegue, y la ruta del paquete que contiene los ficheros. En este caso yo el paquete lo estoy generando en la máquina de SharePoint en lugar de generarlo en la de TFS.

Es necesario el nombre de la máquina de SharePoint para iniciar una sesión de PowerShell remota sobre ella.

De tal forma que nuestro script maestro de PowerShell puede ser similar al siguiente:

image

Es importante dar permisos de administrador a la cuenta de usuario que ejecuta el proceso de Build en la máquina de SharePoint, para que deje ejecutar el script.

 

Este proceso, es bastante complejo y no sale bien siempre a la primera. Lo ideal es ir poco a poco partiendo de lo más básico y si es necesario ir metiendo trazas de mensajes en el WorkFlow de la plantilla de Build.

Los problemas suelen venir por la configuración de permitir la ejecución de scripts de forma remota (que lo vimos en el post anterior), por la configuración de las llamadas a los scripts maestros (si no se escapan bien las dobles comillas, se puede romper la llamada al script), y por los permisos del usuario de TFS sobre la máquina de SharePoint, que pueden no ser suficientes para permitir ciertas acciones, y habrá que asignarlos manualmente.

Con este post se cierra el tema de los despliegues automatizados. Espero que os sirva de ayuda.

Introducción a los despliegues automatizados. Parte I: PowerShell remoto

La capacidad que tiene PowerShell para ejecutar acciones es muy alta. Desde comandos simples, hasta la posibilidad de hacer scripts complejos. El módulo que incorpora SharePoint de comandos de PowerShell tiene una amplia gama de comandos que permiten realizar una cantidad muy grande de operaciones de todo tipo.


Si en otro post vimos como preparar un paquete de despliegue con una  Build para SharePoint con Team Foundation, existe una posibilidad que va mas allá, permitiendo realizar el despliegue automatizado del paquete generado, como parte de la tarea de la Build. No es una tarea trivial, y hay ciertas configuraciones y conceptos que deben entenderse antes.


Como primera parte de la introducción a los despliegues automatizados de SharePoint con TFS, vamos a ver la capacidad de ejecutar comandos de PowerShell de forma remota, que va a ser el mecanismo que se usará para realizar dichos despliegues.


La idea es que desde una máquina, abramos PowerShell, y a través de una serie de comandos, podamos ejecutar acciones sobra otra máquina (que también cuenta con PowerShell, claro). Vamos con un ejemplo:
Supongamos que tenemos dos máquinas, una con SharePoint 2010 (“demossp2010dc”), y otra una máquina por ejemplo con Windows 7 (“mv7”), y queremos desde ésta última, lanzar una serie de comandos para obtener información de la Web Application y de paso crear un SPWeb dentro de una colección de sitios existente y luego eliminarla.


Lo primero que haremos, será una pequeña comprobación para ver que desde cada máquina tenemos visibilidad sobre la otra, por ejemplo mediante un ping:


image


image


En este caso ambas están en el mismo dominio, y en la máquina MV7 está ejecutando la sesión el usuario: DNSLAB\AdminW7, mientras que en la otra el usuario es: DNSLAB\AdminDe.


Ahora, en la máquina de SharePoint hay que realizar una configuración para habilitar la opción de conexión remota, y modificar la política de ejecución de scripts. Para ello, en dicha máquina:
Ejecución del comando: Enable-PSRemoting, y aceptar las confirmaciones:


image


Posteriormente, el comando: Enable-WSManCredSSP –Role Client * –Force


image

El siguiente no es obligatorio, pero si recomendable, para ampliar la memoria de ejecución: Set-Item WSMan:\localhost\Shell\MaxMemoryPerShellMB 1024

image

Y para la ejecución de scripts se cambia la política. Dependiendo de las necesidades y de lo permisivos que queramos ser hay distintos niveles. Yo voy a poner la más permisiva: Set-ExecutionPolicy ByPass, y aceptar la confirmación:

image

En principio ya estaría listo en cuanto a configuración de PowerShell, pero si intentamos desde la máquina MV7 iniciar una sesión remota, podremos ver un error como el siguiente:

image

Esto es debido a que el usuario de la máquina MV7 no tiene permisos sobre la otra máquina para establecer la sesión.

Solo faltaría añadir al usuario (DNSLAB\AdminW7) de la máquina desde donde se ejecutan los comandos (MV7 ) al grupo de administradores de la máquina contra la que se atacará:

image

Y ahora volver a hacer la prueba (siempre ejecutando el Shell de PowerShell en modo Administrador). El comando: New-PSSession –ComputerName <nombre>

image

Ahora podemos conectar de forma remota contra el Shell de la otra máquina para lanzar comandos.

Vamos a comprobar que efectivamente podemos por ejemplo lanzar comandos de SharePoint para obtener información, en este caso obtener las Web Application:

image

Nos aparece un mensaje de acceso denegado. Efectivamente, aunque hemos configurado permisos para ejecutar comandos remotamente, en cuanto a la parte de permisos de SharePoint no hemos hecho nada, y este comando está necesitando permisos de la base de datos de SharePoint para obtener la información. Por lo tanto, vamos a darle permisos al usuario de la máquina MV7 en SQL Server:

Primero añadiendo el login del usuario en caso de no existir:

image

Y posteriormente, en la tabla de configuración con permisos en el rol de acceso al Shell de SharePoint y como db_owner:

image

Aceptamos, y volvemos a hacer la prueba en la otra máquina:

image

Ahora si que nos ha dado la información. Vamos por ejemplo a sacar la colección de sitios principal, con idea de luego crear un SPWeb en ella:

image

Y ahora la creación del SPWeb:

image

Ha vuelto a aparecer un nuevo error. En este caso, estamos intentando atacar con el usuario AdminW7 la base de datos de contenido de la Web Application, y en esa base de datos no hemos dado ningún tipo de permiso al usuario. Por lo tanto, vamos a dárselos. Db_owner sobre la base de datos de contenido:

image

Volvemos a ejecutar el comando:

image

Y un nuevo error aparece. En este caso da menos información que el anterior. Lo que está ocurriendo es que este usuario ahora tiene permisos para hacer cambios en la base de datos, pero estamos creando un SPWeb dentro de una colección de sitios, y las colecciones de sitios tienen permisos propios. Deberemos dar permisos al usuario dentro de la colección de sitios. Yo le voy a incluir como parte de los administradores de la colección:

image

Y vuelvo a probar:

image

Ahora el resultado es el esperado. Para comprobar que también puedo eliminar la web creada:

image

También ha sido correcta la ejecución. Podemos terminar la sesión usando Exit-PSSession:

image


Hemos podido comprobar la capacidad de ejecución de comandos de forma remota con PowerShell contra SharePoint. La parte de los permisos es lo que más problemas puede causarnos, y dependiendo de lo permisivos que seamos podemos ahorrar tiempo o no. Podríamos haber dado permisos al usuario sobre toda la instancia de base de datos como db_sysadmin y no tener que ir buscando las necesarias y dar el permiso correcto.

Podéis probar a unificar los comandos lanzados en un script, ubicar dicho script en la máquina de SharePoint, y a través de una sesión remota ejecutarlo y ver el resultado, ya que hemos configurado la política para que nos deje ejecutar scripts por remoto.

Hacer una Build en TFS 2010 para SharePoint Server 2010

Habrá casos en que dispongamos de un TFS 2010 como repositorio del código que estamos desarrollando. En estos casos, podemos sacarle partido a las Build automáticas, para preparar paquetes que estén listos para desplegar en cualquier momento.
De forma estandar, TFS nos va a dejar compilar la solución o los proyectos que la forman, incluso generando la salida de los paquetes WSP, pero cuando tengamos por ejemplo ficheros de script, ya sean Bat o PowerShell, tendremos que modificar el workflow de la plantilla de la Build, con el fin de poder volcar en una carpeta únicamente los ficheros necesarios para el despliegue de la solución, que en caso de ejemplo serán los paquetes WSP junto con sus script de PowerShell.
La idea es la siguiente: Teniendo una solución con n proyectos de SharePoint 2010, vamos a modificar la plantilla genérica de Build para añadir un proceso que se encargue de crear una carpeta llamada Deploy en la que vamos a dejar únicamente los paquetes WSP y los scripts de PowerShell. Veamos cómo sería el proceso:
Lo primero sería tener una estructura de proyecto en la que tengamos localizados nuestros scripts. Para el ejemplo usaremos la siguiente:
image_thumb1
Ahora vamos a hacer una copia de la plantilla por defecto, que es DefaultTemplate, para ello, localizamos la carpeta donde están las plantillas y hacemos una copia de ella:
image_thumb72
La renombramos para tenerla bien localizada, por ejemplo SPTemplate, y la añadimos al control de código, y posteriormente protegemos todos los cambios (check in):
image_thumb73
Ahora creamos una nueva definición de build, que use nuestra plantilla, desde la ventana del Team Explorer:
image_thumb14
En la pestaña de Process, en el apartado de Build process template vamos a añadir la plantilla que acabamos de copiar. Para ello, hacemos clic en el botón “New” y seleccionamos la plantilla existente:
image_thumb5
A continuación seleccionamos la solución que vamos a compilar en el proceso de build:
image_thumb74
En el apartado de Advanced es muy importante indicar como argumento del MSBuild Arguments la generación de paquete a true. De esta forma en la salida se generarán los WSP pertinentes:
image_thumb75
Hasta aquí la generación de la build, sin la modificación del Workflow. Podemos generar una para ver cómo queda la salida:
image_thumb76
El paquete WSP se ha generado, pero de los scripts ni rastro. Sin modificar aún el Workflow, existe la posibilidad de indicar que queremos que un script aparezca en la salida de la build, desde las propiedades del elemento:
image_thumb15
A mi esta solución no me gusta, porque en la salida va a generar la misma estructura que la que hay en el proyecto, y cuando se trata de proyectos complejos con muchos elementos y una estructura de árbol más compleja, la salida de la build no es muy limpia. Lo ideal es tener una carpeta adicional en la salida, que llamaremos Deploy, y en ella forzaremos al proceso de build a que deje en ella tanto los paquetes como los scripts.
Para ello, vamos a modificar la plantilla que anteriormente copiamos, la SPTemplate. Desde la ventana de Souce Control Explorer abrimos la plantilla haciendo doble clic sobre ella. Se abrirá el Workflow, que es bastante grande, así que lo siguiente será contraer todos los procesos para que quede de la siguiente manera:
image_thumb17
A continuación vamos a entrar en el proceso de “Run On Agent”, que es donde vamos a crear nuestra “ampliación“ del workflow, al final del todo:
image_thumb19
Para ello, desde la Toolbox, vamos a añadir un control de Secuencia, justo al final y lo llamaremos Deploy Package:
image_thumb21
Ahora entramos en el proceso que hemos creado. El proceso lo vamos a dividir en tres partes, una parte en la que vamos a crear la carpeta en donde vamos a dejar los ficheros necesarios para un despliegue (WSP y PowerShell), otra parte en la que vamos a copiar a esa carpeta los ficheros WSP que se generan en la salida, y otra parte en la que vamos a copiar en esa carpeta los scripts de PowerShell. Crearíamos por lo tanto otras tres secuencias dentro de nuestro nuevo proceso:
image_thumb23
Vamos a empezar por el primero, el Create Folder, así que hacemos doble clic sobre él, y a continuación vamos a crear una Variable que va a servir para almacenar la ruta a la carpeta que vamos a crear después:
image_thumb25
image_thumb77
En la expresión introducimos lo siguiente:

String.Format("{0}\{1}", BuildDetail.DropLocation, "Deploy")


image_thumb78

Y en el ámbito (Scope) de la variable, indicamos “Run On Agent”, para poder usarla posteriormente en otra secuencia:

image_thumb79

Ahora metemos un proceso de creación de directorio:

image_thumb80

Y en sus propiedades indicamos que el directorio a crear es nuestra variable:

image_thumb81

Siempre podréis ir haciendo check in a los cambios para ir validando que el funcionamiento es el esperado.

Ahora vamos con el siguiente proceso, el que copia los paquetes WSP. Para ello, lo que haremos será hacer una búsqueda de los WSP que la build a generado, y copiarlos a nuestra carpeta de Deploy. Lo primero será crear una variable para almacenar los WSP que el proceso de búsqueda encuentre:

image_thumb82

Y ahora vamos a crear un proceso para buscar esos ficheros, usando el control de FindMatchingFiles:

image_thumb39

image_thumb83


En la propiedad Result indicamos la variable que acabamos de crear, y en la propiedad MatchPattern, introducimos lo siguiente:



String.Format("{0}\*.wsp", BuildDetail.DropLocation)


Eso hará que el proceso busque todos los ficheros WSP que hay en la salida de la build. Ahora con un control foreach, vamos a copiar cada paquete que ha encontrado (en este caso sólo habrá uno) a la carpeta de Deploy, que tenemos guardada en otra variable ya creada:

image_thumb45

Y las propiedades de este foreach serían las siguientes:

image_thumb47

Si ahora entramos en el proceso foreach, haciendo doble clic sobre él, veremos que tenemos una parte “body” vacía. Ahí vamos a meter un control de InvokeProcess, en donde vamos a invocar al programa xcopy para que realice la copia del fichero, que lo recogemos en la variable “item”:

image_thumb50

image_thumb52

Quedaría así:

image_thumb55

Y en las propiedades del proceso, en Arguments introducimos lo siguiente:



String.Format("""{0}"" ""{1}""", item, FolderPath)







y en FileName: “xcopy.exe”. El resto lo dejamos como está:

image_thumb57

Recordad que en este punto podéis probar la build haciendo check in de la plantilla, para ver si el paquete ha sido copiado a la carpeta deseada.

Por último, vamos a copiar los scripts de PowerShell.El proceso es similar al anterior, con la diferencia de que aquí vamos a indicar la ruta donde se encuentran los scripts. Para ello, ahora vamos a entrar en el proceso de Copia de ficheros de script, y como en el caso anterior, primero vamos a crear una variable donde se guarden los ficheros que vamos a copiar:

image_thumb84

Lo siguiente es insertar un control de FindMatchingFiles, para buscar los scripts en la ubicación que indiquemos, y en las propiedades MatchPattern indicar la ruta de los scripts de la siguiente forma:





String.Format
("{0}\Main\src\SPBuildTest\SPProjectOne\Deploy\Scripts\*.ps1",
 SourcesDirectory)


y en Result indicamos la variable PSFiles que acabamos de crear:

image_thumb85

Igual que con los paquetes WSP, ahora habrá que crear un proceso foreach para copiar cada script que ha encontrado:

image_thumb86

Y dentro del body del foreach, el InvokeProcess que se encargará de realizar la copia. En este caso, el proceso de copia es exactamente igual que el anterior:

image_thumb87

Hacemos Check in a los cambios, y generamos una nueva build para comprobar el resultado obtenido:

image_thumb88

Podemos ver que se ha generado tal y como deseábamos, un paquete de solución de SharePoint y los scripts necesarios para su despliegue.

Este caso es el más simple, pero la idea se puede aplicar a proyectos que generan más paquetes en su salida o que tienen más scripts, distinguiendo entre scripts de producción y desarrollo por ejemplo.

SharePoint Between Racks © 2012
. Con la tecnología de Blogger.

¡Compártelo!


Estoy en LinkedIn!


Ve mi perfil en LinkedIn!