Message ID | 20190908114935.1012-1-freifunk@adrianschmutzler.de |
---|---|
State | Rejected |
Headers | show |
diff --git a/src/packages/fff/fff-nodewatcher/Makefile b/src/packages/fff/fff-nodewatcher/Makefile index be5f267a..0ed6684d 100644 --- a/src/packages/fff/fff-nodewatcher/Makefile +++ b/src/packages/fff/fff-nodewatcher/Makefile @@ -1,7 +1,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=fff-nodewatcher -PKG_RELEASE:=54 +PKG_RELEASE:=55 PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) diff --git a/src/packages/fff/fff-nodewatcher/files/usr/sbin/nodewatcher b/src/packages/fff/fff-nodewatcher/files/usr/sbin/nodewatcher index 09f6843d..c9044fe8 100755 --- a/src/packages/fff/fff-nodewatcher/files/usr/sbin/nodewatcher +++ b/src/packages/fff/fff-nodewatcher/files/usr/sbin/nodewatcher @@ -12,7 +12,7 @@ if ! lock -n "$lockfile"; then fi trap "lock -u \"$lockfile\"" INT TERM EXIT -SCRIPT_VERSION="54" +SCRIPT_VERSION="55" #Get the configuration from the uci configuration file #If it does not exists, then get it from a normal bash file with variables. @@ -291,6 +291,16 @@ crawl() { DATA=$DATA"<batman_adv_originators>$batman_adv_originators</batman_adv_originators>" DATA=$DATA"<batman_adv_gateway_mode>$batman_adv_gateway_mode</batman_adv_gateway_mode>" DATA=$DATA"<batman_adv_gateway_list>$batman_adv_gateway_list</batman_adv_gateway_list>" + + if [ -s /etc/config/babeld ]; then + BABELS="$(echo dump | nc ::1 33123 | grep '^add neighbour' | + awk -v RS='\n' \ + '{r = gensub(/.*add neighbour.*address ([0-9a-fA-F:]*) +if +([^ ]+).* cost +([0-9.]+).*/, \ + "<neighbour><ip>\\1</ip><outgoing_interface>\\2</outgoing_interface><link_cost>\\3</link_cost></neighbour>", "g"); print r;}')" + + DATA=$DATA"<babel_neighbours>$BABELS</babel_neighbours>" + fi + DATA=$DATA"<client_count>$client_count</client_count>" DATA=$DATA"<clients>$dataclient</clients>" DATA=$DATA"$dataair"
Hallo Adrian, On 08.09.19 13:49, Adrian Schmutzler wrote: > diff --git a/src/packages/fff/fff-nodewatcher/files/usr/sbin/nodewatcher b/src/packages/fff/fff-nodewatcher/files/usr/sbin/nodewatcher > index 09f6843d..c9044fe8 100755 > --- a/src/packages/fff/fff-nodewatcher/files/usr/sbin/nodewatcher > +++ b/src/packages/fff/fff-nodewatcher/files/usr/sbin/nodewatcher > @@ -12,7 +12,7 @@ if ! lock -n "$lockfile"; then > fi > trap "lock -u \"$lockfile\"" INT TERM EXIT > > -SCRIPT_VERSION="54" > +SCRIPT_VERSION="55" > > #Get the configuration from the uci configuration file > #If it does not exists, then get it from a normal bash file with variables. > @@ -291,6 +291,16 @@ crawl() { > DATA=$DATA"<batman_adv_originators>$batman_adv_originators</batman_adv_originators>" > DATA=$DATA"<batman_adv_gateway_mode>$batman_adv_gateway_mode</batman_adv_gateway_mode>" > DATA=$DATA"<batman_adv_gateway_list>$batman_adv_gateway_list</batman_adv_gateway_list>" > + > + if [ -s /etc/config/babeld ]; then > + BABELS="$(echo dump | nc ::1 33123 | grep '^add neighbour' | > + awk -v RS='\n' \ > + '{r = gensub(/.*add neighbour.*address ([0-9a-fA-F:]*) +if +([^ ]+).* cost +([0-9.]+).*/, \ > + "<neighbour><ip>\\1</ip><outgoing_interface>\\2</outgoing_interface><link_cost>\\3</link_cost></neighbour>", "g"); print r;}')" 'printf "%s", r' statt 'print r' verwenden? Dann kommt da kein '\n' mitten ins XML. Verrückt, was da für ein foo raus kommt, wenn man so simple Dinge in Shell parsen möchte.. Man müsste das irgendwie geschickt in eine Map (String -> Value) verwandeln.. Ich hab mich da mal an etwas awk versucht: > awk '{ for (i=2; i < NF; i += 2) { vars[$i] = $(i+1) }} { printf "%s" vars["cost"] }' bzw. insgesamt dann > awk '{ for (i=2; i < NF; i += 2) { vars[$i] = $(i+1) }} \ > { printf "<neighbour><ip>%s</ip><outgoing_interface>%s</outgoing_interface><link_cost>%s</link_cost></neighbour>\n", vars["address"], vars["if"], vars["cost"] }' Was hältst du davon? Gruß Fabian
Hallo Fabian, ich habe bei dem Patch nur schnell den aktuellen Stand zusammengemergt und nicht mehr darüber nachgedacht. Ich schaue mir deinen Vorschlag gelegentlich mal an, wenn ich Zeit habe. Grüße Adrian
Moin BABELS=$(echo dump |nc ::1 33123 | awk '/^add neighbour/ {print "<neighbour>"$5"<outgoing_interface>babel</outgoing_interface></neighbour>"}') DATA=$DATA"<clients>$dataclient</clients>" DATA=$DATA"<babel_neighbours>$BABELS</babel_neighbours>" DATA=$DATA"$dataair" Grüße Tim Am Sonntag, den 08.09.2019, 13:49 +0200 schrieb Adrian Schmutzler: > This adds layer 3 neighbors and their cost/penalty values > to the values sent by alfred and thus makes them available > in Monitoring. > > Signed-off-by: Adrian Schmutzler <freifunk@adrianschmutzler.de> > --- > src/packages/fff/fff-nodewatcher/Makefile | 2 +- > .../fff/fff-nodewatcher/files/usr/sbin/nodewatcher | 12 > +++++++++++- > 2 files changed, 12 insertions(+), 2 deletions(-) > > diff --git a/src/packages/fff/fff-nodewatcher/Makefile > b/src/packages/fff/fff-nodewatcher/Makefile > index be5f267a..0ed6684d 100644 > --- a/src/packages/fff/fff-nodewatcher/Makefile > +++ b/src/packages/fff/fff-nodewatcher/Makefile > @@ -1,7 +1,7 @@ > include $(TOPDIR)/rules.mk > > PKG_NAME:=fff-nodewatcher > -PKG_RELEASE:=54 > +PKG_RELEASE:=55 > > PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) > > diff --git a/src/packages/fff/fff- > nodewatcher/files/usr/sbin/nodewatcher b/src/packages/fff/fff- > nodewatcher/files/usr/sbin/nodewatcher > index 09f6843d..c9044fe8 100755 > --- a/src/packages/fff/fff-nodewatcher/files/usr/sbin/nodewatcher > +++ b/src/packages/fff/fff-nodewatcher/files/usr/sbin/nodewatcher > @@ -12,7 +12,7 @@ if ! lock -n "$lockfile"; then > fi > trap "lock -u \"$lockfile\"" INT TERM EXIT > > -SCRIPT_VERSION="54" > +SCRIPT_VERSION="55" > > #Get the configuration from the uci configuration file > #If it does not exists, then get it from a normal bash file with > variables. > @@ -291,6 +291,16 @@ crawl() { > DATA=$DATA"<batman_adv_originators>$batman_adv_originators</batm > an_adv_originators>" > DATA=$DATA"<batman_adv_gateway_mode>$batman_adv_gateway_mode</ba > tman_adv_gateway_mode>" > DATA=$DATA"<batman_adv_gateway_list>$batman_adv_gateway_list</ba > tman_adv_gateway_list>" > + > + if [ -s /etc/config/babeld ]; then > + BABELS="$(echo dump | nc ::1 33123 | grep '^add neighbour' | > + awk -v RS='\n' \ > + '{r = gensub(/.*add neighbour.*address ([0-9a-fA- > F:]*) +if +([^ ]+).* cost +([0-9.]+).*/, \ > + "<neighbour><ip>\\1</ip><outgoing_interface>\\2</out > going_interface><link_cost>\\3</link_cost></neighbour>", "g"); print > r;}')" > + > + DATA=$DATA"<babel_neighbours>$BABELS</babel_neighbours>" > + fi > + > DATA=$DATA"<client_count>$client_count</client_count>" > DATA=$DATA"<clients>$dataclient</clients>" > DATA=$DATA"$dataair"
Hey Tim, so war es ursprünglich mal, ja. Die Position der Parameter kann sich aber ändern. Bei "cost", welches in Adrians Patch für das senden der rxcost an das Monitoring verwendet wird, ist das beispielsweise so, weil in der Mitte noch "rtt" und "rttcost" dazu kommen. Generell würde ich eine Lösung vorziehen, bei der der Output (mehr oder weniger) sinnvoll geparsed wird, auch wenn sich die Reihenfolge der Parameter ändert. Gruß Fabian On 08.09.19 16:53, Tim Niemeyer wrote: > Moin > > BABELS=$(echo dump |nc ::1 33123 | awk '/^add neighbour/ {print "<neighbour>"$5"<outgoing_interface>babel</outgoing_interface></neighbour>"}') > > DATA=$DATA"<clients>$dataclient</clients>" > DATA=$DATA"<babel_neighbours>$BABELS</babel_neighbours>" > DATA=$DATA"$dataair" > > Grüße > Tim > > Am Sonntag, den 08.09.2019, 13:49 +0200 schrieb Adrian Schmutzler: >> This adds layer 3 neighbors and their cost/penalty values >> to the values sent by alfred and thus makes them available >> in Monitoring. >> >> Signed-off-by: Adrian Schmutzler <freifunk@adrianschmutzler.de> >> --- >> src/packages/fff/fff-nodewatcher/Makefile | 2 +- >> .../fff/fff-nodewatcher/files/usr/sbin/nodewatcher | 12 >> +++++++++++- >> 2 files changed, 12 insertions(+), 2 deletions(-) >> >> diff --git a/src/packages/fff/fff-nodewatcher/Makefile >> b/src/packages/fff/fff-nodewatcher/Makefile >> index be5f267a..0ed6684d 100644 >> --- a/src/packages/fff/fff-nodewatcher/Makefile >> +++ b/src/packages/fff/fff-nodewatcher/Makefile >> @@ -1,7 +1,7 @@ >> include $(TOPDIR)/rules.mk >> >> PKG_NAME:=fff-nodewatcher >> -PKG_RELEASE:=54 >> +PKG_RELEASE:=55 >> >> PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) >> >> diff --git a/src/packages/fff/fff- >> nodewatcher/files/usr/sbin/nodewatcher b/src/packages/fff/fff- >> nodewatcher/files/usr/sbin/nodewatcher >> index 09f6843d..c9044fe8 100755 >> --- a/src/packages/fff/fff-nodewatcher/files/usr/sbin/nodewatcher >> +++ b/src/packages/fff/fff-nodewatcher/files/usr/sbin/nodewatcher >> @@ -12,7 +12,7 @@ if ! lock -n "$lockfile"; then >> fi >> trap "lock -u \"$lockfile\"" INT TERM EXIT >> >> -SCRIPT_VERSION="54" >> +SCRIPT_VERSION="55" >> >> #Get the configuration from the uci configuration file >> #If it does not exists, then get it from a normal bash file with >> variables. >> @@ -291,6 +291,16 @@ crawl() { >> DATA=$DATA"<batman_adv_originators>$batman_adv_originators</batm >> an_adv_originators>" >> DATA=$DATA"<batman_adv_gateway_mode>$batman_adv_gateway_mode</ba >> tman_adv_gateway_mode>" >> DATA=$DATA"<batman_adv_gateway_list>$batman_adv_gateway_list</ba >> tman_adv_gateway_list>" >> + >> + if [ -s /etc/config/babeld ]; then >> + BABELS="$(echo dump | nc ::1 33123 | grep '^add neighbour' | >> + awk -v RS='\n' \ >> + '{r = gensub(/.*add neighbour.*address ([0-9a-fA- >> F:]*) +if +([^ ]+).* cost +([0-9.]+).*/, \ >> + "<neighbour><ip>\\1</ip><outgoing_interface>\\2</out >> going_interface><link_cost>\\3</link_cost></neighbour>", "g"); print >> r;}')" >> + >> + DATA=$DATA"<babel_neighbours>$BABELS</babel_neighbours>" >> + fi >> + >> DATA=$DATA"<client_count>$client_count</client_count>" >> DATA=$DATA"<clients>$dataclient</clients>" >> DATA=$DATA"$dataair" >
Moin Du meinst der neightboor ist nicht auf Platz 5 oder was jetzt? Ich würde jetzt nicht groß an den Parametern rumeiern und gar mehr Daten ans monitoring schicken. Das ist eine einfache Lösung die tut. Tim Am 8. September 2019 20:40:43 MESZ schrieb "Fabian Bläse" <fabian@blaese.de>: >Hey Tim, > >so war es ursprünglich mal, ja. >Die Position der Parameter kann sich aber ändern. Bei "cost", welches >in Adrians Patch für das senden der rxcost an das Monitoring verwendet >wird, ist das beispielsweise so, weil in der Mitte noch "rtt" und >"rttcost" dazu kommen. > >Generell würde ich eine Lösung vorziehen, bei der der Output (mehr oder >weniger) sinnvoll geparsed wird, auch wenn sich die Reihenfolge der >Parameter ändert. > >Gruß >Fabian > >On 08.09.19 16:53, Tim Niemeyer wrote: >> Moin >> >> BABELS=$(echo dump |nc ::1 33123 | awk '/^add neighbour/ {print >"<neighbour>"$5"<outgoing_interface>babel</outgoing_interface></neighbour>"}') > >> >> DATA=$DATA"<clients>$dataclient</clients>" > >> DATA=$DATA"<babel_neighbours>$BABELS</babel_neighbours>" > >> DATA=$DATA"$dataair" >> >> Grüße >> Tim >> >> Am Sonntag, den 08.09.2019, 13:49 +0200 schrieb Adrian Schmutzler: >>> This adds layer 3 neighbors and their cost/penalty values >>> to the values sent by alfred and thus makes them available >>> in Monitoring. >>> >>> Signed-off-by: Adrian Schmutzler <freifunk@adrianschmutzler.de> >>> --- >>> src/packages/fff/fff-nodewatcher/Makefile | 2 +- >>> .../fff/fff-nodewatcher/files/usr/sbin/nodewatcher | 12 >>> +++++++++++- >>> 2 files changed, 12 insertions(+), 2 deletions(-) >>> >>> diff --git a/src/packages/fff/fff-nodewatcher/Makefile >>> b/src/packages/fff/fff-nodewatcher/Makefile >>> index be5f267a..0ed6684d 100644 >>> --- a/src/packages/fff/fff-nodewatcher/Makefile >>> +++ b/src/packages/fff/fff-nodewatcher/Makefile >>> @@ -1,7 +1,7 @@ >>> include $(TOPDIR)/rules.mk >>> >>> PKG_NAME:=fff-nodewatcher >>> -PKG_RELEASE:=54 >>> +PKG_RELEASE:=55 >>> >>> PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) >>> >>> diff --git a/src/packages/fff/fff- >>> nodewatcher/files/usr/sbin/nodewatcher b/src/packages/fff/fff- >>> nodewatcher/files/usr/sbin/nodewatcher >>> index 09f6843d..c9044fe8 100755 >>> --- a/src/packages/fff/fff-nodewatcher/files/usr/sbin/nodewatcher >>> +++ b/src/packages/fff/fff-nodewatcher/files/usr/sbin/nodewatcher >>> @@ -12,7 +12,7 @@ if ! lock -n "$lockfile"; then >>> fi >>> trap "lock -u \"$lockfile\"" INT TERM EXIT >>> >>> -SCRIPT_VERSION="54" >>> +SCRIPT_VERSION="55" >>> >>> #Get the configuration from the uci configuration file >>> #If it does not exists, then get it from a normal bash file with >>> variables. >>> @@ -291,6 +291,16 @@ crawl() { >>> >DATA=$DATA"<batman_adv_originators>$batman_adv_originators</batm >>> an_adv_originators>" >>> >DATA=$DATA"<batman_adv_gateway_mode>$batman_adv_gateway_mode</ba >>> tman_adv_gateway_mode>" >>> >DATA=$DATA"<batman_adv_gateway_list>$batman_adv_gateway_list</ba >>> tman_adv_gateway_list>" >>> + >>> + if [ -s /etc/config/babeld ]; then >>> + BABELS="$(echo dump | nc ::1 33123 | grep '^add neighbour' >| >>> + awk -v RS='\n' \ >>> + '{r = gensub(/.*add neighbour.*address ([0-9a-fA- >>> F:]*) +if +([^ ]+).* cost +([0-9.]+).*/, \ >>> + >"<neighbour><ip>\\1</ip><outgoing_interface>\\2</out >>> going_interface><link_cost>\\3</link_cost></neighbour>", "g"); print >>> r;}')" >>> + >>> + DATA=$DATA"<babel_neighbours>$BABELS</babel_neighbours>" >>> + fi >>> + >>> DATA=$DATA"<client_count>$client_count</client_count>" >>> DATA=$DATA"<clients>$dataclient</clients>" >>> DATA=$DATA"$dataair" >>
Hallo Tim, On 08.09.19 21:11, Tim Niemeyer wrote: > Moin > > Du meinst der neightboor ist nicht auf Platz 5 oder was jetzt? Genau. Da bekannt ist, dass die Positionen nicht immer gleich sind, finde ich das Parsen nach statischer Position nicht ordentlich. Hast du dir mal meinen awk angeschaut? Der parsed immer ein Key-Value Paar weg, somit kann man leicht auf alle Paare zugreifen. > > Ich würde jetzt nicht groß an den Parametern rumeiern und gar mehr Daten ans monitoring schicken. Das ist eine einfache Lösung die tut. Zumindest die rxcost finde ich schon durchaus hilfreich im Monitoring zu haben.. Gruß Fabian
Genau den Schnipsel verwende ich schon die ganze Zeit und hatte noch nie Probleme damit: Reviewed-by: Christian Dresel <fff@chrisi01.de> Gruß Christian On 08.09.19 13:49, Adrian Schmutzler wrote: > This adds layer 3 neighbors and their cost/penalty values > to the values sent by alfred and thus makes them available > in Monitoring. > > Signed-off-by: Adrian Schmutzler <freifunk@adrianschmutzler.de> > --- > src/packages/fff/fff-nodewatcher/Makefile | 2 +- > .../fff/fff-nodewatcher/files/usr/sbin/nodewatcher | 12 +++++++++++- > 2 files changed, 12 insertions(+), 2 deletions(-) > > diff --git a/src/packages/fff/fff-nodewatcher/Makefile b/src/packages/fff/fff-nodewatcher/Makefile > index be5f267a..0ed6684d 100644 > --- a/src/packages/fff/fff-nodewatcher/Makefile > +++ b/src/packages/fff/fff-nodewatcher/Makefile > @@ -1,7 +1,7 @@ > include $(TOPDIR)/rules.mk > > PKG_NAME:=fff-nodewatcher > -PKG_RELEASE:=54 > +PKG_RELEASE:=55 > > PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) > > diff --git a/src/packages/fff/fff-nodewatcher/files/usr/sbin/nodewatcher b/src/packages/fff/fff-nodewatcher/files/usr/sbin/nodewatcher > index 09f6843d..c9044fe8 100755 > --- a/src/packages/fff/fff-nodewatcher/files/usr/sbin/nodewatcher > +++ b/src/packages/fff/fff-nodewatcher/files/usr/sbin/nodewatcher > @@ -12,7 +12,7 @@ if ! lock -n "$lockfile"; then > fi > trap "lock -u \"$lockfile\"" INT TERM EXIT > > -SCRIPT_VERSION="54" > +SCRIPT_VERSION="55" > > #Get the configuration from the uci configuration file > #If it does not exists, then get it from a normal bash file with variables. > @@ -291,6 +291,16 @@ crawl() { > DATA=$DATA"<batman_adv_originators>$batman_adv_originators</batman_adv_originators>" > DATA=$DATA"<batman_adv_gateway_mode>$batman_adv_gateway_mode</batman_adv_gateway_mode>" > DATA=$DATA"<batman_adv_gateway_list>$batman_adv_gateway_list</batman_adv_gateway_list>" > + > + if [ -s /etc/config/babeld ]; then > + BABELS="$(echo dump | nc ::1 33123 | grep '^add neighbour' | > + awk -v RS='\n' \ > + '{r = gensub(/.*add neighbour.*address ([0-9a-fA-F:]*) +if +([^ ]+).* cost +([0-9.]+).*/, \ > + "<neighbour><ip>\\1</ip><outgoing_interface>\\2</outgoing_interface><link_cost>\\3</link_cost></neighbour>", "g"); print r;}')" > + > + DATA=$DATA"<babel_neighbours>$BABELS</babel_neighbours>" > + fi > + > DATA=$DATA"<client_count>$client_count</client_count>" > DATA=$DATA"<clients>$dataclient</clients>" > DATA=$DATA"$dataair" >
Hallo, ich bevorzuge das awk von Fabian. Gruss Robert Am 08.09.19 um 15:34 schrieb Fabian Bläse: > Hallo Adrian, > > On 08.09.19 13:49, Adrian Schmutzler wrote: >> diff --git a/src/packages/fff/fff-nodewatcher/files/usr/sbin/nodewatcher b/src/packages/fff/fff-nodewatcher/files/usr/sbin/nodewatcher >> index 09f6843d..c9044fe8 100755 >> --- a/src/packages/fff/fff-nodewatcher/files/usr/sbin/nodewatcher >> +++ b/src/packages/fff/fff-nodewatcher/files/usr/sbin/nodewatcher >> @@ -12,7 +12,7 @@ if ! lock -n "$lockfile"; then >> fi >> trap "lock -u \"$lockfile\"" INT TERM EXIT >> >> -SCRIPT_VERSION="54" >> +SCRIPT_VERSION="55" >> >> #Get the configuration from the uci configuration file >> #If it does not exists, then get it from a normal bash file with variables. >> @@ -291,6 +291,16 @@ crawl() { >> DATA=$DATA"<batman_adv_originators>$batman_adv_originators</batman_adv_originators>" >> DATA=$DATA"<batman_adv_gateway_mode>$batman_adv_gateway_mode</batman_adv_gateway_mode>" >> DATA=$DATA"<batman_adv_gateway_list>$batman_adv_gateway_list</batman_adv_gateway_list>" >> + >> + if [ -s /etc/config/babeld ]; then >> + BABELS="$(echo dump | nc ::1 33123 | grep '^add neighbour' | >> + awk -v RS='\n' \ >> + '{r = gensub(/.*add neighbour.*address ([0-9a-fA-F:]*) +if +([^ ]+).* cost +([0-9.]+).*/, \ >> + "<neighbour><ip>\\1</ip><outgoing_interface>\\2</outgoing_interface><link_cost>\\3</link_cost></neighbour>", "g"); print r;}')" > 'printf "%s", r' statt 'print r' verwenden? Dann kommt da kein '\n' mitten ins XML. > > Verrückt, was da für ein foo raus kommt, wenn man so simple Dinge in Shell parsen möchte.. Man müsste das irgendwie geschickt in eine Map (String -> Value) verwandeln.. Ich hab mich da mal an etwas awk versucht: >> awk '{ for (i=2; i < NF; i += 2) { vars[$i] = $(i+1) }} { printf "%s" vars["cost"] }' > bzw. insgesamt dann >> awk '{ for (i=2; i < NF; i += 2) { vars[$i] = $(i+1) }} \ >> { printf "<neighbour><ip>%s</ip><outgoing_interface>%s</outgoing_interface><link_cost>%s</link_cost></neighbour>\n", vars["address"], vars["if"], vars["cost"] }' > Was hältst du davon? > > Gruß > Fabian >
This adds layer 3 neighbors and their cost/penalty values to the values sent by alfred and thus makes them available in Monitoring. Signed-off-by: Adrian Schmutzler <freifunk@adrianschmutzler.de> --- src/packages/fff/fff-nodewatcher/Makefile | 2 +- .../fff/fff-nodewatcher/files/usr/sbin/nodewatcher | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-)