Merge lp:~akuzminsky/twindb-agent/bug-1410509 into lp:twindb-agent

Proposed by Aleksandr Kuzminsky
Status: Merged
Approved by: Ovais Tariq
Approved revision: 19
Merged at revision: 3
Proposed branch: lp:~akuzminsky/twindb-agent/bug-1410509
Merge into: lp:twindb-agent
Diff against target: 747 lines (+250/-123)
10 files modified
Makefile (+94/-6)
support/deb/debian/changelog (+0/-15)
support/deb/debian/control (+13/-6)
support/deb/debian/twindb.init (+31/-5)
support/deb/debian/twindb.manpages (+1/-1)
support/deb/debian/twindb.postinst (+9/-11)
support/rpm/rpmmacros (+0/-2)
support/rpm/twindb.spec.template (+3/-2)
support/twindb (+3/-3)
twindb.py (+96/-72)
To merge this branch: bzr merge lp:~akuzminsky/twindb-agent/bug-1410509
Reviewer Review Type Date Requested Status
Ovais Tariq Approve
Review via email: mp+246837@code.launchpad.net

Commit message

To post a comment you must log in.
5. By root <root@ubuntu-lucid>

Make the packager's full name and email match to ones from the packager GPG key

6. By root <root@ubuntu-lucid>

fix arithmetic expansion error in shell

7. By root <root@ubuntu-lucid>

Use a template @@CODENAME@@ in changelog. It is replaced by a build script

8. By root <root@ubuntu-lucid>

sh-compatible increment is fixed again

9. By root <root@ubuntu-lucid>

show registration hint only if the agent isn't registred

10. By root <root@ubuntu-lucid>

On lucid sys.path doen't include path where mysql-connector-python installs its modules

11. By root <root@ubuntu-lucid>

Include OS codename into debian package version

12. By root <root@ubuntu-lucid>

package version ++

13. By root <root@ubuntu-lucid>

Use UNRELEASED as target name, otherwise dch throws and error

14. By root <root@ubuntu-lucid>

Version ++

15. By root <root@ubuntu-lucid>

updated changelog

Revision history for this message
Ovais Tariq (ovais-tariq) wrote :

The Makefile target "build-deb" builds the package in the .build directory. But the "build-rpm" package builds the rpm in the directory /root/rpmbuild/ Should we use identical directories for both targets?

16. By Aleksandr Kuzminsky

Build rpm packages in local .build directory instead of /root/rpmbuild

Revision history for this message
Ovais Tariq (ovais-tariq) wrote :
Download full text (4.2 KiB)

Have the dependencies for the deb package not been specified?

I am able to install the package using:
dpkg -i /tmp/twindb_src/.build/twindb_0.1.32-1.wheezy_all.deb

Although the dependencies are not installed on the system. It should have failed.
root@server55-dev-debian-74:~# dpkg -l | grep twindb
ii twindb 0.1.32-1.wheezy all This is a TwinDB agent - a tool that takes backups from MySQL server

When I try to start twindb agent it fails which is expected:
root@server55-dev-debian-74:~# twindb --help
Traceback (most recent call last):
  File "/usr/bin/twindb", line 27, in <module>
    import mysql.connector
ImportError: No module named mysql.connector

And then uninstalling and purging fails because pre-removal script is failing:
root@server55-dev-debian-74:~# apt-get remove twindb
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages were automatically installed and are no longer required:
  mysql-server percona-xtrabackup
Use 'apt-get autoremove' to remove them.
The following packages will be REMOVED:
  twindb
0 upgraded, 0 newly installed, 1 to remove and 68 not upgraded.
After this operation, 129 kB disk space will be freed.
Do you want to continue [Y/n]? y
(Reading database ... 72372 files and directories currently installed.)
Removing twindb ...
Pid file(/var/run/twindb.pid) doesn't exist.
invoke-rc.d: initscript twindb, action "stop" failed.
dpkg: error processing twindb (--remove):
 subprocess installed pre-removal script returned error exit status 1
Traceback (most recent call last):
  File "/usr/bin/twindb", line 27, in <module>
    import mysql.connector
ImportError: No module named mysql.connector
================================================================================
TwinDB client is installed.
Now you need to register this server. To do so run:

twindb --register <registration code>

To obtain the registration code follow link https://console.twindb.com/?get_code
================================================================================
Starting TwinDB agent ... OK
Errors were encountered while processing:
 twindb
E: Sub-process /usr/bin/dpkg returned an error code (1)

root@server55-dev-debian-74:~# dpkg -r twindb
(Reading database ... 72372 files and directories currently installed.)
Removing twindb ...
Pid file(/var/run/twindb.pid) doesn't exist.
invoke-rc.d: initscript twindb, action "stop" failed.
dpkg: error processing twindb (--remove):
 subprocess installed pre-removal script returned error exit status 1
Traceback (most recent call last):
  File "/usr/bin/twindb", line 27, in <module>
    import mysql.connector
ImportError: No module named mysql.connector
================================================================================
TwinDB client is installed.
Now you need to register this server. To do so run:

twindb --register <registration code>

To obtain the registration code follow link https://console.twindb.com/?get_code
================================================================================
Starting TwinDB agent ... OK
Errors were encountered while processing:
 twindb

...

Read more...

review: Needs Fixing
17. By root <root@ubuntu-lucid>

* add mysql-connector-python as dependency in Debian packages
* Number of small fixes in twindb init script for Debian

Revision history for this message
Ovais Tariq (ovais-tariq) wrote :

The deb package gets installed but following errors are reported:

Setting up twindb (0.1.32-1.wheezy) ...
       2015-01-21 04:05:02,893: twindb: ERROR: is_registered():760: Failed to decode
       {"success":false,"errors":{"msg":"Ignoring request without type","msg_debug":null}}

The complete installation log is as follows:
       [2015-01-21T04:04:47+00:00] INFO: bash[build_twindb_deb] sending run action to bash[install-twindb-agent-deb] (immediate)
         * bash[install-twindb-agent-deb] action run[2015-01-21T04:04:47+00:00] INFO: Processing bash[install-twindb-agent-deb] action run (twindb-agent::dev line 100)
Reading package lists... Done
Building dependency tree... 0%
Building dependency tree
Reading state information... 0%
Reading state information... Done
   lding data structures... 0%
Building data structures... Done
   lding data structures... 0%
Building data structures... Done
0% [Working]
Get:1 http://deb.twindb.com/ wheezy/main mysql-connector-python all 2.0.2-1debian7.6 [111 kB]
Fetched 111 kB in 0s (0 B/s)
       Selecting previously unselected package mysql-server.
(Reading database ... 72352 files and directories currently installed.)
       Unpacking mysql-server (from .../mysql-server_5.5.40-0+wheezy1_all.deb) ...
       Selecting previously unselected package mysql-connector-python.
       Unpacking mysql-connector-python (from .../mysql-connector-python_2.0.2-1debian7.6_all.deb) ...
       Selecting previously unselected package percona-xtrabackup.
       Unpacking percona-xtrabackup (from .../percona-xtrabackup_2.2.8-5059-1.wheezy_amd64.deb) ...
       Setting up mysql-server (5.5.40-0+wheezy1) ...
       Setting up mysql-connector-python (2.0.2-1debian7.6) ...
       Setting up percona-xtrabackup (2.2.8-5059-1.wheezy) ...
       Selecting previously unselected package twindb.
(Reading database ... 72492 files and directories currently installed.)
       Unpacking twindb (from .../twindb_0.1.32-1.wheezy_all.deb) ...
       Setting up twindb (0.1.32-1.wheezy) ...
       2015-01-21 04:05:02,893: twindb: ERROR: is_registered():760: Failed to decode
       {"success":false,"errors":{"msg":"Ignoring request without type","msg_debug":null}}
       ================================================================================
       TwinDB client is installed.
       Now you need to register this server. To do so run:

       twindb --register <registration code>

       To obtain the registration code follow link https://console.twindb.com/?get_code
       ================================================================================
Starting TwinDB agent ... OK
       Processing triggers for man-db ...
Fetched 111 kB in 0s (0 B/s)

Revision history for this message
Ovais Tariq (ovais-tariq) wrote :
Download full text (3.8 KiB)

The twindb agent fails to register though. Following is the complete log of the test run:

  1) twindb agent is able to register Command "/usr/bin/twindb --register 0f6714f735a06a488ec9279f59d0a3f2" exit_status should eq 0
     Failure/Error: its(:exit_status) { should eq 0 }

       expected: 0
            got: 1

              (compared using ==)
              /bin/sh -c /usr/bin/twindb\ --register\ 0f6714f735a06a488ec9279f59d0a3f2
              2015-01-21 04:06:49,112: twindb: INFO: check_gpg():241: Looks like GPG never ran. Initializing GPG configuration
       2015-01-21 04:06:54,341: twindb: INFO: install_api_pub_key():205: Installing twindb public key
       2015-01-21 04:06:54,537: twindb: INFO: install_api_pub_key():214: Twindb public key successfully installed
       gpg: key A8AD9889: public key "TwinDB (TwinDB API Portal) <email address hidden>" imported
       gpg: Total number processed: 1
       gpg: imported: 1 (RSA: 1)
       2015-01-21 04:06:54,743: twindb: INFO: gen_gpg_keypair():336: Generating GPG keys pair for <email address hidden>
       2015-01-21 04:06:54,949: twindb: INFO: gen_gpg_keypair():337: It may take really, really long time. Please be patient.
       gpg: Generating a standard key
       ...+++++
       ....+++++
       .............+++++
       .+++++
       gpg: key 3C43C384 marked as ultimately trusted
       gpg: done
       2015-01-21 04:06:56,481: twindb: INFO: action_handler_register():1012: Registering TwinDB agent with code 0f6714f735a06a488ec9279f59d0a3f2
       2015-01-21 04:06:56,801: twindb: INFO: action_handler_register():1013: The agent needs to generate cryptographically strong keys.
       2015-01-21 04:06:57,119: twindb: INFO: action_handler_register():1014: It may take really, really long time. Please be patient.
       2015-01-21 04:06:57,431: twindb: INFO: action_handler_register():1019: Reading GPG public key of <email address hidden>.
       2015-01-21 04:06:57,746: twindb: INFO: action_handler_register():1031: Generating SSH keys pair.
       Generating public/private rsa key pair.
       Created directory '/root/.ssh'.
       Your identification has been saved in /root/.ssh/twindb.key.
       Your public key has been saved in /root/.ssh/twindb.key.pub.
       The key fingerprint is:
       cc:b8:87:b7:06:fd:f3:8b:78:e7:7d:6a:12:6d:2e:a4 root@server55-dev-debian-74
       The key's randomart image is:
       +--[ RSA 2048]----+
       | |
       | |
       | |
       | + |
       | ..S . |
       | .o. o o |
       | o.o. o + |
       | o.oE.+.o .|
       | .o..=+=oo |
       +-----------------+
       2015-01-21 04:06:58,170: twindb: INFO: action_handler_register():1037: Reading SSH public key from /root/.ssh/twindb.key.pub.
       Traceback (most recent call last):
         File "/usr/bin/twindb", line 2283, in <module>
           main()
         File "/usr/bin/twindb", line 2257, in main
           action_handler_register(regcode)
         File "/usr/bin/twindb", line 104...

Read more...

Revision history for this message
Ovais Tariq (ovais-tariq) wrote :

twindb --is-registered also appears to be broken:

         2) twindb agent is able to register Command "/usr/bin/twindb --is-registered" stdout should match /YES/
            Failure/Error: its(:stdout) { should match /YES/ }
              expected "2015-01-21 04:07:04,075: twindb: ERROR: is_registered():760: Failed to decode \n{\"success\":false,\"errors\":{\"msg\":\"Ignoring request without type\",\"msg_debug\":null}}\n" to match /YES/

Revision history for this message
Ovais Tariq (ovais-tariq) :
review: Needs Fixing
18. By root <email address hidden>

Don't send debug logs to dispatcher, otherwise it's impossible to read debug output

19. By root <root@ubuntu-lucid>

pretty debug messages in get_response()

20. By Aleksandr Kuzminsky

* Debian standard bump
* Removed mysql-server and mysql-client dependencies. I'm not sure all MySQL vendors provide mysql-server. Besides, if mysql-server-5.5 is installed it will try to install mysql-server.
* Use get_mysql_connection() to manage connection to MySQL
* Pretty print JSON response from the dispatcher and ignore empty responses
* Make debug output nicer and more readable

Revision history for this message
Ovais Tariq (ovais-tariq) wrote :
Download full text (5.0 KiB)

It fails when agent interacts with the production dispatcher as well.

/usr/bin/twindb -g --dispatcher dispatcher.twindb.com --is-registered
       2015-01-23 18:07:07,432: twindb: DEBUG: get_response():485: Enter get_response(uri=api.php)
       2015-01-23 18:07:07,514: twindb: DEBUG: get_response():495: Sending to dispatcher.twindb.com: {
           "params": {
        "server_id": "1f84dfce-41b0-4a84-a661-add8b4067ee5"

           },
           "type": "is_registered"
       }
       2015-01-23 18:07:07,521: twindb: DEBUG: encrypt():386: Public key of <email address hidden> is not installed.
       2015-01-23 18:07:07,522: twindb: DEBUG: encrypt():387: Will not encrypt message
       2015-01-23 18:07:07,616: twindb: DEBUG: get_response():521: Response from http://dispatcher.twindb.com//api.php : {
           "errors": {
        "msg": "Ignoring request without type",
        "msg_debug": null
           },
           "success": false
       }
       2015-01-23 18:07:07,616: twindb: ERROR: is_registered():759: Failed to decode
       {"success":false,"errors":{"msg":"Ignoring request without type","msg_debug":null}}
       2015-01-23 18:07:07,618: twindb: DEBUG: exit_on_error():2005: Traceback (most recent call last):
         File "/usr/bin/twindb", line 750, in is_registered
           msg_enc = response_body_decoded["response"]
       KeyError: u'response'

/usr/bin/twindb -g --dispatcher dispatcher.twindb.com --register 0f6714f735a06a488ec9279f59d0a3f2
       2015-01-23 18:07:07,775: twindb: INFO: check_gpg():243: Looks like GPG never ran. Initializing GPG configuration
       2015-01-23 18:07:07,776: twindb: INFO: install_api_pub_key():207: Installing twindb public key
       2015-01-23 18:07:07,789: twindb: INFO: install_api_pub_key():216: Twindb public key successfully installed
       gpg: keyring `/root/.gnupg//secring.gpg' created
       gpg: keyring `/root/.gnupg//pubring.gpg' created
       gpg: /root/.gnupg//trustdb.gpg: trustdb created
       gpg: key A8AD9889: public key "TwinDB (TwinDB API Portal) <email address hidden>" imported
       2015-01-23 18:07:07,797: twindb: INFO: gen_gpg_keypair():338: Generating GPG keys pair for <email address hidden>
       2015-01-23 18:07:07,798: twindb: INFO: gen_gpg_keypair():339: It may take really, really long time. Please be patient.
       gpg: Total number processed: 1
       gpg: imported: 1 (RSA: 1)
       gpg: Generating a standard key
       gpg: key 94B30215 marked as ultimately trusted
       gpg: done
       2015-01-23 18:07:08,334: twindb: DEBUG: check_env():271: Enviroment is OK
       2015-01-23 18:07:08,335: twindb: INFO: action_handler_register():1011: Registering TwinDB agent with code 0f6714f735a06a488ec9279f59d0a3f2

       2015-01-23 18:07:08,335: twindb: INFO: action_handler_register():1012: The agent needs to generate cryptographically strong keys.
       2015-01-23 18:07:08,336: twindb: INFO: action_handler_register():1013: It may take really, really long time. Please be patient.
       2015-01-23 18:07:08,336: twindb: INFO: action_handler_register():1018: Reading GPG public key of 1f84dfce-41b0-4a84-a661-add8b4067ee5@twin...

Read more...

Revision history for this message
Ovais Tariq (ovais-tariq) wrote :

Above test was done on CentOS 6.5

21. By Aleksandr Kuzminsky

add lsof as dependency

22. By Aleksandr Kuzminsky

add lsof as dependency in rpm spec file too

23. By Aleksandr Kuzminsky

Connect to MySQL with option_files only if at least one options file was found

24. By Aleksandr Kuzminsky

Specify socket for innobackupex

25. By Aleksandr Kuzminsky

Select only processes that fully match mysqld

26. By Aleksandr Kuzminsky

Parse all command line arguments before calling is_registered()

Revision history for this message
Ovais Tariq (ovais-tariq) wrote :

All tests pass.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile'
2--- Makefile 2015-01-16 07:41:06 +0000
3+++ Makefile 2015-01-24 21:00:42 +0000
4@@ -1,12 +1,16 @@
5 # TwinDB agent Makefile
6
7 spec = support/rpm/twindb.spec
8-client_version = "`grep Version: ${spec} | awk '{ print $$2}' | head -1`"
9-client_release = "`grep Release: ${spec} | awk '{ print $$2}' | head -1`"
10+client_version = 0.1.32
11+client_release = 1
12 rh_release = "$$(r=`lsb_release -sr | cut -d . -f1`; if [ \"$$r\" = \"n/a\" ] ; then echo latest; else echo $$r; fi)"
13+rpmmacros = /usr/lib/rpm/macros:/usr/lib/rpm/redhat/macros:/etc/rpm/macros:support/rpm/rpmmacros
14+deb_release = "$$(lsb_release -sc)"
15 build_dir = .build
16 src_dir = twindb-${client_version}
17-top_dir = /root/rpmbuild
18+pwd := $(shell pwd)
19+top_dir = ${pwd}/${build_dir}/rpmbuild
20+deb_packages = build-essential devscripts debhelper
21
22 .PHONY: help rpm sign rpmmacros
23
24@@ -40,13 +44,21 @@
25
26 clean:
27 rm -f twindb twindb.8.gz
28+ rm -f support/rpm/twindb.spec
29+ rm -rf .build
30
31-build-rpm: rpmmacros
32+archive:
33 rm -rf "${build_dir}"
34 mkdir -p "${build_dir}/${src_dir}"
35 cp -R * "${build_dir}/${src_dir}"
36- tar zcf "${top_dir}/SOURCES/${src_dir}.tar.gz" -C "${build_dir}" "${src_dir}"
37- rpmbuild -ba ${spec}
38+ tar zcf "${build_dir}/${src_dir}.tar.gz" -C "${build_dir}" "${src_dir}"
39+
40+# RPM stuff
41+build-rpm: rpmmacros spec archive
42+ mkdir -p "${top_dir}/SOURCES/"
43+ mkdir -p "${top_dir}/BUILD/"
44+ mv "${build_dir}/${src_dir}.tar.gz" "${top_dir}/SOURCES/${src_dir}.tar.gz"
45+ rpmbuild --macros=${rpmmacros} -D '%_topdir ${top_dir}' -ba ${spec}
46
47 sign-rpm:
48 rpm --addsign ${top_dir}/RPMS/noarch/twindb-${client_version}-${client_release}.noarch.rpm
49@@ -59,3 +71,79 @@
50
51 rpmmacros:
52 if ! test -f ~/.rpmmacros ; then cp support/rpm/rpmmacros ~/.rpmmacros; fi
53+
54+spec:
55+ sed -e 's/@@VERSION@@/${client_version}/' -e 's/@@RELEASE@@/${client_release}/' \
56+ support/rpm/twindb.spec.template > support/rpm/twindb.spec
57+
58+# Debian stuff
59+deb-dependencies:
60+ @echo "Checking dependencies"
61+ @for p in ${deb_packages}; \
62+ do echo -n "$$p ... " ; \
63+ if test -z "`dpkg -l | grep $$p`"; \
64+ then \
65+ echo "$$p ... NOT installed"; \
66+ apt-get -y install $$p; \
67+ else \
68+ echo "installed"; \
69+ fi ; \
70+ done
71+
72+build-deb: deb-dependencies archive
73+ mv "${build_dir}/${src_dir}.tar.gz" "${build_dir}/twindb_${client_version}.orig.tar.gz"
74+ cp -R support/deb/debian/ "${build_dir}/${src_dir}"
75+ rm -f "${build_dir}/${src_dir}/debian/changelog"
76+ @echo "Generating changelog"
77+ @export DEBEMAIL="TwinDB Packager (TwinDB packager key) <packager@twindb.com>" ; \
78+ export version=${client_version}-${client_release} ; \
79+ export tags="`bzr tags | sort -nk2 | cut -d" " -f1`" ; \
80+ export last_tag=`bzr tags | sort -nrk2 | head -1 | cut -d" " -f1` ; \
81+ export prev_tag="" ; \
82+ if [ "$$last_tag" != "$$version" ] ; \
83+ then \
84+ echo "Error: Last tag $$last_tag doesn't match current version $$version in Makefile" ; \
85+ echo "Please create tag $$version:" ; \
86+ echo "bzr tag $$version" ; \
87+ exit 1 ; \
88+ fi ; \
89+ cd support/deb/ ; \
90+ for tag in $$tags ; \
91+ do \
92+ echo -n "Version: $$tag. Revisions " ; \
93+ if test -z "$$prev_tag" ; \
94+ then \
95+ start_revno=1 ; \
96+ else \
97+ export start_revno=`bzr tags | grep $$prev_tag | awk '{ print $$2 }'` ; \
98+ export start_revno=$$(( $$start_revno + 1 )); \
99+ fi; \
100+ echo -n "$$start_revno .. " ; \
101+ export end_revno=`bzr tags | grep $$tag | awk '{ print $$2 }'` ; \
102+ echo "$$end_revno" ; \
103+ if ! test -f debian/changelog || test -z "`grep "twindb .*$$tag.*UNRELEASED; urgency=" debian/changelog`"; \
104+ then \
105+ echo "Adding new version $$tag.UNRELEASED to the changelog" ; \
106+ if ! test -f debian/changelog; then export opt_create='--create' ; else export opt_create='' ; fi ; \
107+ echo "dch $$opt_create -v $$tag.UNRELEASED --package twindb --distribution UNRELEASED "New version $$tag"" ; \
108+ dch $$opt_create -v $$tag.UNRELEASED --package twindb --distribution UNRELEASED "New version $$tag" ; \
109+ for revno in `seq $$end_revno -1 $$start_revno`; \
110+ do \
111+ export log_msg="`bzr log -r $$revno --line`" ; \
112+ echo "Adding log entry to version $$tag: $$log_msg" ; \
113+ dch --append "$$log_msg" ; \
114+ done ; \
115+ fi ; \
116+ export prev_tag=$$tag ; \
117+ done ; \
118+ cd - > /dev/null;
119+ export distr=`lsb_release -sc` ; \
120+ sed s/UNRELEASED/$$distr/g support/deb/debian/changelog > "${build_dir}/${src_dir}/debian/changelog"
121+ cd "${build_dir}/${src_dir}" && debuild -us -uc
122+
123+sign-deb:
124+ cd "${build_dir}"; debsign -kpackager@twindb.com *.changes
125+
126+upload-deb:
127+ ssh ubuntu@deb.twindb.com "mkdir -p ~/deb/`lsb_release -sc`"
128+ scp ${build_dir}/*.changes ${build_dir}/*.dsc ${build_dir}/*.tar.gz ${build_dir}/*.deb ubuntu@deb.twindb.com:~/deb/`lsb_release -sc`
129
130=== added file 'support/deb/debian/changelog'
131--- support/deb/debian/changelog 1970-01-01 00:00:00 +0000
132+++ support/deb/debian/changelog 2015-01-24 21:00:42 +0000
133@@ -0,0 +1,36 @@
134+twindb (0.1.32-1.UNRELEASED) UNRELEASED; urgency=low
135+
136+ * New version 0.1.32-1
137+ * 14: root 2015-01-19 {0.1.32-1} Version ++
138+ * 13: root 2015-01-19 Use UNRELEASED as target name, otherwise dch
139+ throws and error
140+
141+ -- TwinDB Packager (TwinDB packager key) <packager@twindb.com> Mon, 19 Jan 2015 05:08:48 -0800
142+
143+twindb (0.1.31-2.UNRELEASED) UNRELEASED; urgency=low
144+
145+ * New version 0.1.31-2
146+ * 12: root 2015-01-19 {0.1.31-2} package version ++
147+ * 11: root 2015-01-19 Include OS codename into debian package version
148+ * 10: root 2015-01-18 On lucid sys.path doen't include path where
149+ mysql-connector-python installs its modules
150+ * 9: root 2015-01-18 show registration hint only if the agent isn't
151+ registred
152+ * 8: root 2015-01-18 sh-compatible increment is fixed again
153+ * 7: root 2015-01-18 Use a template @@CODENAME@@ in changelog. It is
154+ replaced by a build script
155+ * 6: root 2015-01-18 fix arithmetic expansion error in shell
156+ * 5: root 2015-01-18 Make the packager's full name and email match to
157+ ones from the packager GPG key
158+ * 4: root 2015-01-17 Makefile can build Debian packages
159+ * 3: root 2015-01-15 Moved Makefile from twindb project
160+ * 2: root 2015-01-15 Fixed Bug #1403183
161+
162+ -- TwinDB Packager (TwinDB packager key) <packager@twindb.com> Mon, 19 Jan 2015 04:47:04 -0800
163+
164+twindb (0.1.31-1.UNRELEASED) UNRELEASED; urgency=low
165+
166+ * New version 0.1.31-1
167+ * 1: Aleksandr Kuzminsky 2015-01-15 {0.1.31-1} Initial import
168+
169+ -- TwinDB Packager (TwinDB packager key) <packager@twindb.com> Thu, 15 Jan 2015 20:25:52 -0800
170
171=== removed file 'support/deb/debian/changelog'
172--- support/deb/debian/changelog 2015-01-16 07:41:06 +0000
173+++ support/deb/debian/changelog 1970-01-01 00:00:00 +0000
174@@ -1,15 +0,0 @@
175-twindb (0.0.80-1) testing; urgency=low
176-
177- * Fixes https://bugs.launchpad.net/twindb-client/+bug/1273461
178- * Package numbering is synced with RPM
179-
180- -- Aleksandr Kuzminsky <packager@twindb.com> Mon, 27 Jan 2014 17:14:01 -0500
181-
182-
183-twindb (0.0-0.1) testing; urgency=low
184-
185- * Non-maintainer upload.
186- * Initial release. (Closes: #1234)
187-
188- -- Aleksandr Kuzminsky <aleksandr.kuzminsky@twindb.com> Fri, 15 Nov 2013 17:26:15 +0000
189-
190
191=== modified file 'support/deb/debian/control'
192--- support/deb/debian/control 2015-01-16 07:41:06 +0000
193+++ support/deb/debian/control 2015-01-24 21:00:42 +0000
194@@ -1,13 +1,20 @@
195 Source: twindb
196-Maintainer: Aleksandr Kuzminsky <packager@twindb.com>
197+Homepage: https://twindb.com
198+Maintainer: TwinDB Packager (TwinDB packager key) <packager@twindb.com>
199 Section: database
200 Priority: optional
201-Standards-Version: 3.8.4
202+Standards-Version: 3.9.3
203 Build-Depends: debhelper (>= 7)
204+Vcs-Browser: https://code.launchpad.net/twindb-agent
205+Vcs-Bzr: bzr+ssh://bazaar.launchpad.net/%2Bbranch/twindb-agent/
206
207 Package: twindb
208 Architecture: all
209-Depends: ${misc:Depends}, percona-xtrabackup, php5-json | php5-common, php5-cli, gnupg, php5-mcrypt, mysql-server, mysql-client, php5-mysql
210-Description: tool to manage backups of MySQL server
211- This is a TwinDB agent - a tool that takes backups from MySQL server
212-
213+Section: database
214+Priority: optional
215+Depends: ${misc:Depends}, lsof, percona-xtrabackup, gnupg, python (>= 2.6.0), mysql-connector-python (>= 2.0.0)
216+Description: backup and recovery tool for MySQL
217+ TwinDB is online backup service for MySQL.
218+ It includes scheduler, retention policy manager, storage.
219+ Visit us on https://twindb.com to get more details
220+Homepage: https://twindb.com
221
222=== modified file 'support/deb/debian/twindb.init'
223--- support/deb/debian/twindb.init 2015-01-16 07:41:06 +0000
224+++ support/deb/debian/twindb.init 2015-01-24 21:00:42 +0000
225@@ -23,19 +23,45 @@
226 'start')
227 if test -f $pid_file
228 then
229- $0 stop
230+ #$0 stop
231+ echo "Pid file $pid_file exists."
232+ echo "Either another instance of twindb is running or $pid_file is abandoned file."
233+ echo "Please stop twindb agent first."
234+ echo "$0 stop"
235+ exit 1
236 fi
237+ echo -n "Starting TwinDB agent ... "
238 /usr/bin/twindb --start > /dev/null 2>&1 &
239+ echo "OK"
240 ;;
241 'stop')
242 if test -f $pid_file
243 then
244+ echo -n "Stopping TwinDB agent ... "
245+ pid=`cat "$pid_file"`
246+ wait_timeout=300
247 /usr/bin/twindb --stop
248+ # Wait till agent exits
249+ while kill -0 $pid 2>/dev/null
250+ do
251+ if [ $wait_timeout -lt 1 ]; then break; fi
252+ sleep 1
253+ wait_timeout=$(( $wait_timeout - 1 ))
254+ done
255+ echo "OK"
256+ else
257+ echo "Pid file($pid_file) doesn't exist."
258 fi
259- ;;
260- 'restart'|'reload'|'force-reload')
261- $0 stop
262- $0 start
263+ # Kill all abandoned and hung agents
264+ pkill -9 -f /usr/bin/twindb || true
265+ ;;
266+ 'restart')
267+ $0 stop
268+ $0 start
269+ ;;
270+ 'force-reload')
271+ $0 stop
272+ $0 start
273 ;;
274 'status')
275 if test -f $pid_file && ! test -z "$(ps -p `cat $pid_file` -o pid=)"
276
277=== modified file 'support/deb/debian/twindb.manpages'
278--- support/deb/debian/twindb.manpages 2015-01-16 07:41:06 +0000
279+++ support/deb/debian/twindb.manpages 2015-01-24 21:00:42 +0000
280@@ -1,1 +1,1 @@
281-twindb.man
282+support/twindb.man
283
284=== modified file 'support/deb/debian/twindb.postinst'
285--- support/deb/debian/twindb.postinst 2015-01-16 07:41:06 +0000
286+++ support/deb/debian/twindb.postinst 2015-01-24 21:00:42 +0000
287@@ -2,18 +2,16 @@
288
289 chmod 755 /usr/bin/twindb
290
291-echo "Please run "
292-echo ""
293-echo "twindb --register <registration code>"
294-echo ""
295-echo "to register the server"
296-echo "The registration code you can find on https://twindb.com"
297-
298-# on saucy mcrypt is not loaded in cli php
299-if test -z "`php -m | grep mcrypt`"
300+if [ "`twindb --is-registered`" != "YES" ]
301 then
302- ln -s /etc/php5/conf.d/mcrypt.ini /etc/php5/cli/conf.d/30-mcrypt.ini
303+ echo "================================================================================"
304+ echo "TwinDB client is installed."
305+ echo "Now you need to register this server. To do so run:"
306+ echo ""
307+ echo "twindb --register <registration code>"
308+ echo ""
309+ echo "To obtain the registration code follow link https://console.twindb.com/?get_code"
310+ echo "================================================================================"
311 fi
312-
313 #DEBHELPER#
314
315
316=== modified file 'support/rpm/rpmmacros'
317--- support/rpm/rpmmacros 2015-01-16 07:41:06 +0000
318+++ support/rpm/rpmmacros 2015-01-24 21:00:42 +0000
319@@ -2,5 +2,3 @@
320 %_gpg_name packager@twindb.com
321 %vendor TwinDB LLC
322 %packager packager@twindb.com
323-%_topdir /root/rpmbuild/
324-%_tmppath /root/rpmbuild/tmp
325
326=== renamed file 'support/rpm/twindb.spec' => 'support/rpm/twindb.spec.template'
327--- support/rpm/twindb.spec 2015-01-16 07:41:06 +0000
328+++ support/rpm/twindb.spec.template 2015-01-24 21:00:42 +0000
329@@ -1,6 +1,6 @@
330 Name: twindb
331-Version: 0.1.31
332-Release: 1
333+Version: @@VERSION@@
334+Release: @@RELEASE@@
335 Summary: TwinDB agent for online MySQL backups
336
337 Group: Applications/Databases
338@@ -25,6 +25,7 @@
339
340 Requires: gpg
341 Requires: tar
342+Requires: lsof
343 Requires: chkconfig
344 Requires: procps
345 Requires: mysql
346
347=== modified file 'support/twindb'
348--- support/twindb 2015-01-16 07:41:06 +0000
349+++ support/twindb 2015-01-24 21:00:42 +0000
350@@ -26,7 +26,7 @@
351 echo "Either another instance of twindb is running or $pid_file is abandoned file."
352 echo "Please stop twindb agent first."
353 echo "$0 stop"
354- exit -1
355+ exit 1
356 fi
357 echo -n "Starting TwinDB agent ... "
358 /usr/bin/twindb --start > /dev/null 2>&1 &
359@@ -44,14 +44,14 @@
360 do
361 if [ $wait_timeout -lt 1 ]; then break; fi
362 sleep 1
363- let wait_timeout=$wait_timeout-1
364+ wait_timeout=$(( $wait_timeout - 1 ))
365 done
366 echo "OK"
367 else
368 echo "Pid file($pid_file) doesn't exist."
369 fi
370 # Kill all abandoned and hung agents
371- pkill -9 -f /usr/bin/twindb
372+ pkill -9 -f /usr/bin/twindb || true
373 ;;
374 'restart')
375 $0 stop
376
377=== modified file 'twindb.py'
378--- twindb.py 2015-01-15 21:02:14 +0000
379+++ twindb.py 2015-01-24 21:00:42 +0000
380@@ -19,7 +19,11 @@
381 import json
382 import urllib
383 import re
384-import mysql.connector
385+try:
386+ import mysql.connector
387+except ImportError:
388+ sys.path.insert(0, '/usr/lib/python2.6/site-packages')
389+ import mysql.connector
390 import tempfile
391 import uuid
392
393@@ -109,13 +113,15 @@
394 def emit(self, record):
395 global server_id
396 global job_id
397+ global debug
398+
399 request = {}
400 request["type"] = "log"
401 request["params"] = {}
402 if job_id != 0:
403 request["params"]["job_id"] = job_id
404 request["params"]["msg"] = record.getMessage()
405- if self.log_flag:
406+ if self.log_flag and not debug:
407 self.log_flag = False
408 get_response(request)
409 self.log_flag = True
410@@ -145,6 +151,38 @@
411 -p | --password password MySQL password")
412 return
413
414+
415+def get_mysql_connection(user = None, passwd = None):
416+ global mysql_user
417+ global mysql_password
418+
419+ try:
420+ if user == None:
421+ user = mysql_user
422+ if passwd == None:
423+ passwd = mysql_password
424+ mysql_option_files = []
425+ unix_socket = get_unix_socket()
426+ conn = mysql.connector.connect()
427+ if user != None:
428+ for f in ['/etc/mysql/my.cnf', '/etc/my.cnf', '/root/.my.cnf']:
429+ if os.path.exists(f):
430+ mysql_option_files.append(f)
431+ if mysql_option_files:
432+ conn = mysql.connector.connect(option_files = mysql_option_files, unix_socket = unix_socket)
433+ logger.debug("Connected to MySQL as '%s'@'localhost' with options files %r" % (conn.user, mysql_option_files) )
434+ if not conn.is_connected():
435+ conn = mysql.connector.connect(user = user, passwd = passwd, unix_socket = unix_socket)
436+ logger.debug("Connected to MySQL as %s@localhost " % conn.user)
437+ except mysql.connector.Error as err:
438+ logger.error("Can not connect to local MySQL server")
439+ logger.error("MySQL said: %s" % err.msg)
440+ return None
441+ except:
442+ logger.error("Can not connect to local MySQL server")
443+ logger.error("Unexpected error: %s,%s" % sys.exc_info()[:2]);
444+ return None
445+ return conn
446 # Checks if TwinDB API public key is installed
447 # Returns
448 # True - if the key is installed
449@@ -475,8 +513,7 @@
450
451 uri = "api.php"
452 response_body = None
453- logger.debug("Enter get_response(uri=" + uri + ") with request:")
454- logger.debug(request)
455+ logger.debug("Enter get_response(uri=" + uri + ")")
456 if proto == "http":
457 conn = httplib.HTTPConnection(host)
458 elif proto == "https":
459@@ -486,8 +523,7 @@
460 try:
461 url = proto + "://" + host + "/" + api_dir + "/" + uri
462 conn.connect()
463- logger.debug("Sending to " + host + ":")
464- logger.debug(request)
465+ logger.debug("Sending to " + host + ": %s" % json.dumps(request, indent=4, sort_keys=True))
466 data_json = json.dumps(request)
467 data_json_enc = encrypt(data_json)
468 data_json_enc_urlenc = urllib.urlencode({'data': data_json_enc})
469@@ -502,7 +538,6 @@
470 http_response = conn.getresponse()
471 if(http_response.status == 200):
472 response_body = http_response.read()
473- logger.debug("Response from server: %s" % response_body);
474 if(len(response_body) == 0):
475 return None
476 url = "%(proto)s://%(host)s/%(api_dir)s/%(uri)s" % {
477@@ -511,9 +546,16 @@
478 "api_dir": api_dir,
479 "uri": uri
480 }
481+ d = json.JSONDecoder()
482+ try:
483+ json_object = json.loads(response_body)
484+ except ValueError as e:
485+ msg = response_body
486+ else:
487+ msg = json.dumps(d.decode(response_body), indent=4, sort_keys=True)
488 logger.debug("Response from %(url)s : %(resp)s" % {
489 "url": url,
490- "resp": response_body
491+ "resp": msg
492 })
493 else:
494 logger.error("HTTP error %d %s" % (http_response.status, http_response.reason))
495@@ -575,7 +617,6 @@
496 response_body_decoded = d.decode(response_body)
497 if response_body_decoded:
498 msg_enc = response_body_decoded["response"]
499- logger.debug("Reply from server %s" % msg_enc)
500 msg_pt = d.decode(decrypt(msg_enc))
501 config = msg_pt["data"]
502 logger.info("Got config:\n%s" % json.dumps(sanitize_config(config), indent=4, sort_keys=True))
503@@ -634,10 +675,7 @@
504 logger.error("Unexpected error: %s,%s" % sys.exc_info()[:2])
505 return
506 try:
507- unix_socket = get_unix_socket()
508- logger.debug("Connecting to MySQL as '%s'@'localhost' with password '%s' via socket %s" %
509- (mysql_user, mysql_password, unix_socket))
510- con = mysql.connector.connect(user=mysql_user, passwd=mysql_password, unix_socket = unix_socket)
511+ con = get_mysql_connection(user=mysql_user, passwd=mysql_password)
512 cursor = con.cursor()
513 query = "SELECT PRIVILEGE_TYPE FROM information_schema.USER_PRIVILEGES"
514 logger.debug("Sending query : %s" % query)
515@@ -742,15 +780,18 @@
516 d = json.JSONDecoder()
517 response_body_decoded = d.decode(response_body)
518 if response_body_decoded:
519- msg_enc = response_body_decoded["response"]
520- logger.debug("Reply from server %s" % msg_enc)
521- msg_pt = d.decode(decrypt(msg_enc))
522- registration_status = msg_pt["data"]
523- logger.debug("Got registration status:\n%s" % json.dumps(registration_status, indent=4, sort_keys=True))
524- if msg_pt["error"]:
525- logger.error(msg_pt["error"])
526- exit_on_error(msg_pt["error"])
527- return registration_status["registered"]
528+ if "response" in response_body_decoded:
529+ msg_enc = response_body_decoded["response"]
530+ msg_pt = d.decode(decrypt(msg_enc))
531+ registration_status = msg_pt["data"]
532+ logger.debug("Got registration status:\n%s" % json.dumps(registration_status, indent=4, sort_keys=True))
533+ if msg_pt["error"]:
534+ logger.error(msg_pt["error"])
535+ exit_on_error(msg_pt["error"])
536+ return registration_status["registered"]
537+ else:
538+ logger.debug("No valid response from dispatcher. Conseder agent unregistered")
539+ return False
540 except exceptions.KeyError as err:
541 logger.error("Failed to decode %s" % response_body);
542 exit_on_error(traceback.format_exc())
543@@ -939,25 +980,15 @@
544 return
545
546 def get_slave_status():
547- global mysql_user
548- global mysql_password
549
550 result = dict()
551 # Read master host
552 try:
553- mysql_option_files = []
554- for f in ['/etc/mysql/my.cnf', '/etc/my.cnf', '/root/.my.cnf']:
555- if os.path.exists(f):
556- mysql_option_files.append(f)
557- conn = mysql.connector.connect(option_files=mysql_option_files)
558- if not conn.is_connected():
559- conn = mysql.connector.connect(user=mysql_user, passwd=mysql_password)
560- except mysql.connector.Error as err:
561- logger.error("Can not connect to local MySQL server.")
562- logger.error("MySQL said: %s" % err.msg)
563- exit_on_error(traceback.format_exc())
564- try:
565- cursor = conn.cursor(dictionary=True)
566+ conn = get_mysql_connection()
567+ if conn:
568+ cursor = conn.cursor(dictionary=True)
569+ else:
570+ return None
571
572 result["mysql_server_id"] = None
573 result["mysql_master_server_id"] = None
574@@ -981,9 +1012,9 @@
575 cursor.close()
576 conn.close()
577 except:
578- logger.error("Can not read Master_host from MySQL")
579+ logger.error("Could not read Master_host from MySQL")
580 logger.error("Unexpected error: %s,%s" % sys.exc_info()[:2]);
581- exit_on_error(traceback.format_exc())
582+ return None
583 return result
584
585 # Registers this server in TwinDB dispatcher
586@@ -1042,6 +1073,9 @@
587 cmd += "| awk '{ print $2}'"
588 cmd += "| awk -F/ '{ print $1}'"
589 ss = get_slave_status()
590+ if ss is None:
591+ logger.error("Could not get slave status on this server")
592+ exit_on_error()
593 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
594 local_ip = list()
595 for row in p.stdout:
596@@ -1065,8 +1099,6 @@
597 "local_ip": local_ip
598 }
599 }
600- logger.debug("Registration request:")
601- logger.debug(data)
602 response = get_response(data)
603 if response <> None:
604 jd = json.JSONDecoder()
605@@ -1091,18 +1123,7 @@
606
607 config = get_config()
608 try:
609- mysql_option_files = []
610- for f in ['/etc/mysql/my.cnf', '/etc/my.cnf', '/root/.my.cnf']:
611- if os.path.exists(f):
612- mysql_option_files.append(f)
613- conn = mysql.connector.connect(option_files=mysql_option_files)
614- if not conn.is_connected():
615- conn = mysql.connector.connect(user=mysql_user, passwd=mysql_password)
616- except mysql.connector.Error as err:
617- logger.error("Can not connect to local MySQL server.")
618- logger.error("MySQL said: %s" % err.msg)
619- exit_on_error(traceback.format_exc())
620- try:
621+ conn = get_mysql_connection()
622 q = "GRANT RELOAD, LOCK TABLES, REPLICATION CLIENT, SUPER, CREATE TABLESPACE"
623 q += " ON *.* TO %s@'localhost' IDENTIFIED BY %s"
624 cursor = conn.cursor()
625@@ -1218,16 +1239,13 @@
626 # True - if all necessary privileges are granted
627 # False - if not all necessary privilegers are granted
628
629-def check_mysql_permissions(config, job):
630+def check_mysql_permissions(config):
631 global logger
632
633 try:
634 logger.info("Checking if '%s'@'localhost' has enough rights to backup MySQL" % config["mysql_user"])
635 result = False
636- unix_socket = get_unix_socket()
637- logger.debug("Connecting to MySQL as '%s'@'localhost' with password '%s' via socket %s" %
638- (config["mysql_user"], config["mysql_password"], unix_socket))
639- con = mysql.connector.connect(user=config["mysql_user"], passwd=config["mysql_password"], unix_socket = unix_socket)
640+ con = get_mysql_connection(user=config["mysql_user"], passwd=config["mysql_password"])
641 required_priv = ["RELOAD", "LOCK TABLES", "REPLICATION CLIENT", "SUPER", "CREATE TABLESPACE"]
642 for priv in required_priv:
643 cursor = con.cursor()
644@@ -1363,6 +1381,7 @@
645 xtrabackup_cmd.append("--stream=xbstream")
646 xtrabackup_cmd.append("--user=%s" % mysql_user)
647 xtrabackup_cmd.append("--password=%s" % mysql_password)
648+ xtrabackup_cmd.append("--socket=%s" % get_unix_socket())
649 xtrabackup_cmd.append("--slave-info")
650 xtrabackup_cmd.append("--safe-slave-backup")
651 xtrabackup_cmd.append("--safe-slave-backup-timeout=3600")
652@@ -1457,10 +1476,9 @@
653 try:
654 f, extra_config = tempfile.mkstemp()
655 os.write(f, "[mysqld]\n")
656- mysql_user = config["mysql_user"]
657- mysql_password = config["mysql_password"]
658- unix_socket = get_unix_socket()
659- con = mysql.connector.connect(user = mysql_user, passwd = mysql_password, unix_socket = unix_socket)
660+ con = get_mysql_connection(
661+ user = config["mysql_user"],
662+ passwd = config["mysql_password"])
663 cur = con.cursor()
664 cur.execute("SELECT @@datadir")
665 row = cur.fetchone()
666@@ -1880,7 +1898,7 @@
667 socket = ""
668 try:
669 cmd = [
670- "lsof", "-U", "-c", "mysqld", "-a", "-F", "n"
671+ "lsof", "-U", "-c", "/^mysqld$/", "-a", "-F", "n"
672 ]
673 p = subprocess.Popen(cmd, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
674 cout, cerr = p.communicate()
675@@ -1997,8 +2015,9 @@
676
677 # Reports error removes pid and exits
678
679-def exit_on_error(tb):
680- logger.debug(tb)
681+def exit_on_error(tb = None):
682+ if tb is not None:
683+ logger.debug(tb)
684 remove_pid()
685 sys.exit(2)
686
687@@ -2020,7 +2039,7 @@
688 os.kill(pid, signal.SIGTERM)
689 wait_pid(pid, 300)
690 f.close()
691- except OSError:
692+ except OSError as err:
693 logger.error("Couldn't kill process %d" % pid)
694 logger.error(err)
695 exit_on_error(traceback.format_exc())
696@@ -2090,7 +2109,7 @@
697 global job_id
698
699 try:
700- if not check_mysql_permissions(config, job):
701+ if not check_mysql_permissions(config):
702 return False
703 if job["start_scheduled"] == None:
704 logger.error("Job start time isn't set")
705@@ -2150,6 +2169,8 @@
706 global logger
707 global mysql_user
708 global mysql_password
709+ global debug
710+
711 # Read or generate server id
712 if os.path.exists(init_config):
713 try:
714@@ -2205,6 +2226,7 @@
715 elif opt in ['-p', '--password']:
716 mysql_password = arg
717 elif opt == '-g':
718+ debug = True
719 logger.setLevel(logging.DEBUG)
720 elif opt == '--start':
721 action = "start"
722@@ -2220,11 +2242,7 @@
723 elif opt == '--backup':
724 action = "backup"
725 elif opt == '--is-registered':
726- if is_registered():
727- print("YES")
728- else:
729- print("NO")
730- sys.exit(0)
731+ action = "is-registered"
732 elif opt in ["-h", "--help"]:
733 usage()
734 sys.exit(0)
735@@ -2265,6 +2283,12 @@
736 if not action_handler_backup():
737 logger.error("Failed to take backup")
738 sys.exit(2)
739+ elif action == "is-registered":
740+ if is_registered():
741+ print("YES")
742+ else:
743+ print("NO")
744+ sys.exit(0)
745 else:
746 # If we got there print usage() and exit
747 logger.error("Neither --start nor --stop nor --register is specified")

Subscribers

People subscribed via source and target branches

to all changes: