* [PATCH] KVM test: Modifying finish.exe to support parallel installs
@ 2010-02-11 19:29 Lucas Meneghel Rodrigues
0 siblings, 0 replies; 3+ messages in thread
From: Lucas Meneghel Rodrigues @ 2010-02-11 19:29 UTC (permalink / raw)
To: autotest; +Cc: kvm, anantyog, ryanh, Lucas Meneghel Rodrigues
In order to adapt all the OS unattended installs to parallel
installs, finish.exe also had to be adapted to be a server
instead of a client. These are the modifications needed.
Once the whole patchset is worked out, an updated version
of finish.exe will be shipped on version control.
Signed-off-by: Lucas Meneghel Rodrigues <lmr@redhat.com>
---
client/tests/kvm/deps/finish.cpp | 111 ++++++++++++++++++++------------------
1 files changed, 59 insertions(+), 52 deletions(-)
diff --git a/client/tests/kvm/deps/finish.cpp b/client/tests/kvm/deps/finish.cpp
index 9c2867c..e5ba128 100644
--- a/client/tests/kvm/deps/finish.cpp
+++ b/client/tests/kvm/deps/finish.cpp
@@ -1,12 +1,13 @@
-// Simple app that only sends an ack string to the KVM unattended install
-// watch code.
+// Simple application that creates a server socket, listening for connections
+// of the unattended install test. Once it gets a client connected, the
+// app will send back an ACK string, indicating the install process is done.
//
// You must link this code with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
//
// Author: Lucas Meneghel Rodrigues <lmr@redhat.com>
// Code was adapted from an MSDN sample.
-// Usage: finish.exe [Host OS IP]
+// Usage: finish.exe
// MinGW's ws2tcpip.h only defines getaddrinfo and other functions only for
// the case _WIN32_WINNT >= 0x0501.
@@ -21,24 +22,18 @@
#include <stdlib.h>
#include <stdio.h>
-#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "12323"
-
int main(int argc, char **argv)
{
WSADATA wsaData;
- SOCKET ConnectSocket = INVALID_SOCKET;
- struct addrinfo *result = NULL,
- *ptr = NULL,
- hints;
+ SOCKET ListenSocket = INVALID_SOCKET, ClientSocket = INVALID_SOCKET;
+ struct addrinfo *result = NULL, hints;
char *sendbuf = "done";
- char recvbuf[DEFAULT_BUFLEN];
- int iResult;
- int recvbuflen = DEFAULT_BUFLEN;
+ int iResult, iSendResult;
// Validate the parameters
- if (argc != 2) {
- printf("usage: %s server-name\n", argv[0]);
+ if (argc != 1) {
+ printf("usage: %s", argv[0]);
return 1;
}
@@ -49,72 +44,84 @@ int main(int argc, char **argv)
return 1;
}
- ZeroMemory( &hints, sizeof(hints) );
- hints.ai_family = AF_UNSPEC;
+ ZeroMemory(&hints, sizeof(hints));
+ hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
+ hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
- iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
- if ( iResult != 0 ) {
+ iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
+ if (iResult != 0) {
printf("getaddrinfo failed: %d\n", iResult);
WSACleanup();
return 1;
}
- // Attempt to connect to an address until one succeeds
- for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
-
- // Create a SOCKET for connecting to server
- ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
- ptr->ai_protocol);
- if (ConnectSocket == INVALID_SOCKET) {
- printf("Error at socket(): %ld\n", WSAGetLastError());
- freeaddrinfo(result);
- WSACleanup();
- return 1;
- }
-
- // Connect to server.
- iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
- if (iResult == SOCKET_ERROR) {
- closesocket(ConnectSocket);
- ConnectSocket = INVALID_SOCKET;
- continue;
- }
- break;
+ // Create a SOCKET for connecting to server
+ ListenSocket = socket(result->ai_family, result->ai_socktype,
+ result->ai_protocol);
+ if (ListenSocket == INVALID_SOCKET) {
+ printf("socket failed: %ld\n", WSAGetLastError());
+ freeaddrinfo(result);
+ WSACleanup();
+ return 1;
+ }
+
+ // Setup the TCP listening socket
+ iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
+ if (iResult == SOCKET_ERROR) {
+ printf("bind failed: %d\n", WSAGetLastError());
+ freeaddrinfo(result);
+ closesocket(ListenSocket);
+ WSACleanup();
+ return 1;
}
freeaddrinfo(result);
- if (ConnectSocket == INVALID_SOCKET) {
- printf("Unable to connect to server!\n");
+ iResult = listen(ListenSocket, SOMAXCONN);
+ if (iResult == SOCKET_ERROR) {
+ printf("listen failed: %d\n", WSAGetLastError());
+ closesocket(ListenSocket);
WSACleanup();
return 1;
}
- // Send the ACK buffer
- iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
- if (iResult == SOCKET_ERROR) {
- printf("send failed: %d\n", WSAGetLastError());
- closesocket(ConnectSocket);
+ // Accept a client socket
+ ClientSocket = accept(ListenSocket, NULL, NULL);
+ if (ClientSocket == INVALID_SOCKET) {
+ printf("accept failed: %d\n", WSAGetLastError());
+ closesocket(ListenSocket);
WSACleanup();
return 1;
}
- printf("Bytes Sent: %ld\n", iResult);
+ // No longer need the server socket
+ closesocket(ListenSocket);
+
+ // Send the ack string to the client
+ iSendResult = send(ClientSocket, sendbuf, sizeof(sendbuf), 0);
+ if (iSendResult == SOCKET_ERROR) {
+ printf("send failed: %d\n", WSAGetLastError());
+ closesocket(ClientSocket);
+ WSACleanup();
+ return 1;
+ }
+ // Report the number of bytes sent
+ printf("Bytes sent: %d\n", iSendResult);
- // shutdown the connection since no more data will be sent
- iResult = shutdown(ConnectSocket, SD_SEND);
+ // Shutdown the connection since we're done
+ iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed: %d\n", WSAGetLastError());
- closesocket(ConnectSocket);
+ closesocket(ClientSocket);
WSACleanup();
return 1;
}
- // cleanup
- closesocket(ConnectSocket);
+ // Cleanup
+ closesocket(ClientSocket);
WSACleanup();
return 0;
--
1.6.6.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] KVM test: Modifying finish.exe to support parallel installs
[not found] <2120738685.1596381266164097337.JavaMail.root@zmail05.collab.prod.int.phx2.redhat.com>
@ 2010-02-14 16:21 ` Michael Goldish
2010-02-18 10:07 ` Lucas Meneghel Rodrigues
0 siblings, 1 reply; 3+ messages in thread
From: Michael Goldish @ 2010-02-14 16:21 UTC (permalink / raw)
To: Lucas Meneghel Rodrigues; +Cc: autotest, kvm
----- "Lucas Meneghel Rodrigues" <lmr@redhat.com> wrote:
> In order to adapt all the OS unattended installs to parallel
> installs, finish.exe also had to be adapted to be a server
> instead of a client. These are the modifications needed.
>
> Once the whole patchset is worked out, an updated version
> of finish.exe will be shipped on version control.
>
> Signed-off-by: Lucas Meneghel Rodrigues <lmr@redhat.com>
Now that finish.exe is a server it looks like a stripped version
of rss.exe. Since we're already running rss.exe at the end of
each unattended_install, why not just use VM.remote_login() to
verify that the installation was successful?
> client/tests/kvm/deps/finish.cpp | 111
> ++++++++++++++++++++------------------
> 1 files changed, 59 insertions(+), 52 deletions(-)
>
> diff --git a/client/tests/kvm/deps/finish.cpp
> b/client/tests/kvm/deps/finish.cpp
> index 9c2867c..e5ba128 100644
> --- a/client/tests/kvm/deps/finish.cpp
> +++ b/client/tests/kvm/deps/finish.cpp
> @@ -1,12 +1,13 @@
> -// Simple app that only sends an ack string to the KVM unattended
> install
> -// watch code.
> +// Simple application that creates a server socket, listening for
> connections
> +// of the unattended install test. Once it gets a client connected,
> the
> +// app will send back an ACK string, indicating the install process
> is done.
> //
> // You must link this code with Ws2_32.lib, Mswsock.lib, and
> Advapi32.lib
> //
> // Author: Lucas Meneghel Rodrigues <lmr@redhat.com>
> // Code was adapted from an MSDN sample.
>
> -// Usage: finish.exe [Host OS IP]
> +// Usage: finish.exe
>
> // MinGW's ws2tcpip.h only defines getaddrinfo and other functions
> only for
> // the case _WIN32_WINNT >= 0x0501.
> @@ -21,24 +22,18 @@
> #include <stdlib.h>
> #include <stdio.h>
>
> -#define DEFAULT_BUFLEN 512
> #define DEFAULT_PORT "12323"
> -
> int main(int argc, char **argv)
> {
> WSADATA wsaData;
> - SOCKET ConnectSocket = INVALID_SOCKET;
> - struct addrinfo *result = NULL,
> - *ptr = NULL,
> - hints;
> + SOCKET ListenSocket = INVALID_SOCKET, ClientSocket =
> INVALID_SOCKET;
> + struct addrinfo *result = NULL, hints;
> char *sendbuf = "done";
> - char recvbuf[DEFAULT_BUFLEN];
> - int iResult;
> - int recvbuflen = DEFAULT_BUFLEN;
> + int iResult, iSendResult;
>
> // Validate the parameters
> - if (argc != 2) {
> - printf("usage: %s server-name\n", argv[0]);
> + if (argc != 1) {
> + printf("usage: %s", argv[0]);
> return 1;
> }
>
> @@ -49,72 +44,84 @@ int main(int argc, char **argv)
> return 1;
> }
>
> - ZeroMemory( &hints, sizeof(hints) );
> - hints.ai_family = AF_UNSPEC;
> + ZeroMemory(&hints, sizeof(hints));
> + hints.ai_family = AF_INET;
> hints.ai_socktype = SOCK_STREAM;
> hints.ai_protocol = IPPROTO_TCP;
> + hints.ai_flags = AI_PASSIVE;
>
> // Resolve the server address and port
> - iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
> - if ( iResult != 0 ) {
> + iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
> + if (iResult != 0) {
> printf("getaddrinfo failed: %d\n", iResult);
> WSACleanup();
> return 1;
> }
>
> - // Attempt to connect to an address until one succeeds
> - for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
> -
> - // Create a SOCKET for connecting to server
> - ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
> - ptr->ai_protocol);
> - if (ConnectSocket == INVALID_SOCKET) {
> - printf("Error at socket(): %ld\n", WSAGetLastError());
> - freeaddrinfo(result);
> - WSACleanup();
> - return 1;
> - }
> -
> - // Connect to server.
> - iResult = connect( ConnectSocket, ptr->ai_addr,
> (int)ptr->ai_addrlen);
> - if (iResult == SOCKET_ERROR) {
> - closesocket(ConnectSocket);
> - ConnectSocket = INVALID_SOCKET;
> - continue;
> - }
> - break;
> + // Create a SOCKET for connecting to server
> + ListenSocket = socket(result->ai_family, result->ai_socktype,
> + result->ai_protocol);
> + if (ListenSocket == INVALID_SOCKET) {
> + printf("socket failed: %ld\n", WSAGetLastError());
> + freeaddrinfo(result);
> + WSACleanup();
> + return 1;
> + }
> +
> + // Setup the TCP listening socket
> + iResult = bind(ListenSocket, result->ai_addr,
> (int)result->ai_addrlen);
> + if (iResult == SOCKET_ERROR) {
> + printf("bind failed: %d\n", WSAGetLastError());
> + freeaddrinfo(result);
> + closesocket(ListenSocket);
> + WSACleanup();
> + return 1;
> }
>
> freeaddrinfo(result);
>
> - if (ConnectSocket == INVALID_SOCKET) {
> - printf("Unable to connect to server!\n");
> + iResult = listen(ListenSocket, SOMAXCONN);
> + if (iResult == SOCKET_ERROR) {
> + printf("listen failed: %d\n", WSAGetLastError());
> + closesocket(ListenSocket);
> WSACleanup();
> return 1;
> }
>
> - // Send the ACK buffer
> - iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0
> );
> - if (iResult == SOCKET_ERROR) {
> - printf("send failed: %d\n", WSAGetLastError());
> - closesocket(ConnectSocket);
> + // Accept a client socket
> + ClientSocket = accept(ListenSocket, NULL, NULL);
> + if (ClientSocket == INVALID_SOCKET) {
> + printf("accept failed: %d\n", WSAGetLastError());
> + closesocket(ListenSocket);
> WSACleanup();
> return 1;
> }
>
> - printf("Bytes Sent: %ld\n", iResult);
> + // No longer need the server socket
> + closesocket(ListenSocket);
> +
> + // Send the ack string to the client
> + iSendResult = send(ClientSocket, sendbuf, sizeof(sendbuf), 0);
> + if (iSendResult == SOCKET_ERROR) {
> + printf("send failed: %d\n", WSAGetLastError());
> + closesocket(ClientSocket);
> + WSACleanup();
> + return 1;
> + }
> + // Report the number of bytes sent
> + printf("Bytes sent: %d\n", iSendResult);
>
> - // shutdown the connection since no more data will be sent
> - iResult = shutdown(ConnectSocket, SD_SEND);
> + // Shutdown the connection since we're done
> + iResult = shutdown(ClientSocket, SD_SEND);
> if (iResult == SOCKET_ERROR) {
> printf("shutdown failed: %d\n", WSAGetLastError());
> - closesocket(ConnectSocket);
> + closesocket(ClientSocket);
> WSACleanup();
> return 1;
> }
>
> - // cleanup
> - closesocket(ConnectSocket);
> + // Cleanup
> + closesocket(ClientSocket);
> WSACleanup();
>
> return 0;
> --
> 1.6.6.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] KVM test: Modifying finish.exe to support parallel installs
2010-02-14 16:21 ` [PATCH] KVM test: Modifying finish.exe to support parallel installs Michael Goldish
@ 2010-02-18 10:07 ` Lucas Meneghel Rodrigues
0 siblings, 0 replies; 3+ messages in thread
From: Lucas Meneghel Rodrigues @ 2010-02-18 10:07 UTC (permalink / raw)
To: Michael Goldish; +Cc: kvm, anantyog, ryanh, autotest
On Sun, 2010-02-14 at 11:21 -0500, Michael Goldish wrote:
> ----- "Lucas Meneghel Rodrigues" <lmr@redhat.com> wrote:
>
> > In order to adapt all the OS unattended installs to parallel
> > installs, finish.exe also had to be adapted to be a server
> > instead of a client. These are the modifications needed.
> >
> > Once the whole patchset is worked out, an updated version
> > of finish.exe will be shipped on version control.
> >
> > Signed-off-by: Lucas Meneghel Rodrigues <lmr@redhat.com>
>
> Now that finish.exe is a server it looks like a stripped version
> of rss.exe. Since we're already running rss.exe at the end of
> each unattended_install, why not just use VM.remote_login() to
> verify that the installation was successful?
If we can guarantee that the sshd daemon is up and running by the end of
linux guest installs, then that is a perfectly fine solution. Need to
check though.
> > client/tests/kvm/deps/finish.cpp | 111
> > ++++++++++++++++++++------------------
> > 1 files changed, 59 insertions(+), 52 deletions(-)
> >
> > diff --git a/client/tests/kvm/deps/finish.cpp
> > b/client/tests/kvm/deps/finish.cpp
> > index 9c2867c..e5ba128 100644
> > --- a/client/tests/kvm/deps/finish.cpp
> > +++ b/client/tests/kvm/deps/finish.cpp
> > @@ -1,12 +1,13 @@
> > -// Simple app that only sends an ack string to the KVM unattended
> > install
> > -// watch code.
> > +// Simple application that creates a server socket, listening for
> > connections
> > +// of the unattended install test. Once it gets a client connected,
> > the
> > +// app will send back an ACK string, indicating the install process
> > is done.
> > //
> > // You must link this code with Ws2_32.lib, Mswsock.lib, and
> > Advapi32.lib
> > //
> > // Author: Lucas Meneghel Rodrigues <lmr@redhat.com>
> > // Code was adapted from an MSDN sample.
> >
> > -// Usage: finish.exe [Host OS IP]
> > +// Usage: finish.exe
> >
> > // MinGW's ws2tcpip.h only defines getaddrinfo and other functions
> > only for
> > // the case _WIN32_WINNT >= 0x0501.
> > @@ -21,24 +22,18 @@
> > #include <stdlib.h>
> > #include <stdio.h>
> >
> > -#define DEFAULT_BUFLEN 512
> > #define DEFAULT_PORT "12323"
> > -
> > int main(int argc, char **argv)
> > {
> > WSADATA wsaData;
> > - SOCKET ConnectSocket = INVALID_SOCKET;
> > - struct addrinfo *result = NULL,
> > - *ptr = NULL,
> > - hints;
> > + SOCKET ListenSocket = INVALID_SOCKET, ClientSocket =
> > INVALID_SOCKET;
> > + struct addrinfo *result = NULL, hints;
> > char *sendbuf = "done";
> > - char recvbuf[DEFAULT_BUFLEN];
> > - int iResult;
> > - int recvbuflen = DEFAULT_BUFLEN;
> > + int iResult, iSendResult;
> >
> > // Validate the parameters
> > - if (argc != 2) {
> > - printf("usage: %s server-name\n", argv[0]);
> > + if (argc != 1) {
> > + printf("usage: %s", argv[0]);
> > return 1;
> > }
> >
> > @@ -49,72 +44,84 @@ int main(int argc, char **argv)
> > return 1;
> > }
> >
> > - ZeroMemory( &hints, sizeof(hints) );
> > - hints.ai_family = AF_UNSPEC;
> > + ZeroMemory(&hints, sizeof(hints));
> > + hints.ai_family = AF_INET;
> > hints.ai_socktype = SOCK_STREAM;
> > hints.ai_protocol = IPPROTO_TCP;
> > + hints.ai_flags = AI_PASSIVE;
> >
> > // Resolve the server address and port
> > - iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
> > - if ( iResult != 0 ) {
> > + iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
> > + if (iResult != 0) {
> > printf("getaddrinfo failed: %d\n", iResult);
> > WSACleanup();
> > return 1;
> > }
> >
> > - // Attempt to connect to an address until one succeeds
> > - for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
> > -
> > - // Create a SOCKET for connecting to server
> > - ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
> > - ptr->ai_protocol);
> > - if (ConnectSocket == INVALID_SOCKET) {
> > - printf("Error at socket(): %ld\n", WSAGetLastError());
> > - freeaddrinfo(result);
> > - WSACleanup();
> > - return 1;
> > - }
> > -
> > - // Connect to server.
> > - iResult = connect( ConnectSocket, ptr->ai_addr,
> > (int)ptr->ai_addrlen);
> > - if (iResult == SOCKET_ERROR) {
> > - closesocket(ConnectSocket);
> > - ConnectSocket = INVALID_SOCKET;
> > - continue;
> > - }
> > - break;
> > + // Create a SOCKET for connecting to server
> > + ListenSocket = socket(result->ai_family, result->ai_socktype,
> > + result->ai_protocol);
> > + if (ListenSocket == INVALID_SOCKET) {
> > + printf("socket failed: %ld\n", WSAGetLastError());
> > + freeaddrinfo(result);
> > + WSACleanup();
> > + return 1;
> > + }
> > +
> > + // Setup the TCP listening socket
> > + iResult = bind(ListenSocket, result->ai_addr,
> > (int)result->ai_addrlen);
> > + if (iResult == SOCKET_ERROR) {
> > + printf("bind failed: %d\n", WSAGetLastError());
> > + freeaddrinfo(result);
> > + closesocket(ListenSocket);
> > + WSACleanup();
> > + return 1;
> > }
> >
> > freeaddrinfo(result);
> >
> > - if (ConnectSocket == INVALID_SOCKET) {
> > - printf("Unable to connect to server!\n");
> > + iResult = listen(ListenSocket, SOMAXCONN);
> > + if (iResult == SOCKET_ERROR) {
> > + printf("listen failed: %d\n", WSAGetLastError());
> > + closesocket(ListenSocket);
> > WSACleanup();
> > return 1;
> > }
> >
> > - // Send the ACK buffer
> > - iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0
> > );
> > - if (iResult == SOCKET_ERROR) {
> > - printf("send failed: %d\n", WSAGetLastError());
> > - closesocket(ConnectSocket);
> > + // Accept a client socket
> > + ClientSocket = accept(ListenSocket, NULL, NULL);
> > + if (ClientSocket == INVALID_SOCKET) {
> > + printf("accept failed: %d\n", WSAGetLastError());
> > + closesocket(ListenSocket);
> > WSACleanup();
> > return 1;
> > }
> >
> > - printf("Bytes Sent: %ld\n", iResult);
> > + // No longer need the server socket
> > + closesocket(ListenSocket);
> > +
> > + // Send the ack string to the client
> > + iSendResult = send(ClientSocket, sendbuf, sizeof(sendbuf), 0);
> > + if (iSendResult == SOCKET_ERROR) {
> > + printf("send failed: %d\n", WSAGetLastError());
> > + closesocket(ClientSocket);
> > + WSACleanup();
> > + return 1;
> > + }
> > + // Report the number of bytes sent
> > + printf("Bytes sent: %d\n", iSendResult);
> >
> > - // shutdown the connection since no more data will be sent
> > - iResult = shutdown(ConnectSocket, SD_SEND);
> > + // Shutdown the connection since we're done
> > + iResult = shutdown(ClientSocket, SD_SEND);
> > if (iResult == SOCKET_ERROR) {
> > printf("shutdown failed: %d\n", WSAGetLastError());
> > - closesocket(ConnectSocket);
> > + closesocket(ClientSocket);
> > WSACleanup();
> > return 1;
> > }
> >
> > - // cleanup
> > - closesocket(ConnectSocket);
> > + // Cleanup
> > + closesocket(ClientSocket);
> > WSACleanup();
> >
> > return 0;
> > --
> > 1.6.6.1
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe kvm" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2010-02-18 10:07 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <2120738685.1596381266164097337.JavaMail.root@zmail05.collab.prod.int.phx2.redhat.com>
2010-02-14 16:21 ` [PATCH] KVM test: Modifying finish.exe to support parallel installs Michael Goldish
2010-02-18 10:07 ` Lucas Meneghel Rodrigues
2010-02-11 19:29 Lucas Meneghel Rodrigues
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox