diff mbox series

dry-run option overwritten by IPC request

Message ID 20201122095118.78296-1-sbabic@denx.de
State Accepted
Headers show
Series dry-run option overwritten by IPC request | expand

Commit Message

Stefano Babic Nov. 22, 2020, 9:51 a.m. UTC
An IPC request can contain if the install should run in dry-run mode,
but this overwrites the same option issued with command line parameter.
Store --dry-run into SWUpdate's structure and use it if the request does
not have set any value for dry-run. A request should indicate if dry-run
is set or if the default value (from --dry-run) should be taken.

Signed-off-by: Stefano Babic <sbabic@denx.de>
---
 core/stream_interface.c     | 11 +++++++++--
 core/swupdate.c             |  3 ++-
 doc/source/swupdate-ipc.rst |  4 ++--
 include/network_ipc.h       |  8 +++++++-
 include/swupdate.h          |  1 +
 ipc/network_ipc-if.c        |  1 +
 tools/swupdate-client.c     |  3 ++-
 7 files changed, 24 insertions(+), 7 deletions(-)

Comments

Storm, Christian Nov. 23, 2020, 12:05 p.m. UTC | #1
Hi Stefano,

> An IPC request can contain if the install should run in dry-run mode,
> but this overwrites the same option issued with command line parameter.
> Store --dry-run into SWUpdate's structure and use it if the request does
> not have set any value for dry-run. A request should indicate if dry-run
> is set or if the default value (from --dry-run) should be taken.
> 
> Signed-off-by: Stefano Babic <sbabic@denx.de>
> ---
>  core/stream_interface.c     | 11 +++++++++--
>  core/swupdate.c             |  3 ++-
>  doc/source/swupdate-ipc.rst |  4 ++--
>  include/network_ipc.h       |  8 +++++++-
>  include/swupdate.h          |  1 +
>  ipc/network_ipc-if.c        |  1 +
>  tools/swupdate-client.c     |  3 ++-
>  7 files changed, 24 insertions(+), 7 deletions(-)
> 
> diff --git a/core/stream_interface.c b/core/stream_interface.c
> index 3f8a168..39fa64e 100644
> --- a/core/stream_interface.c
> +++ b/core/stream_interface.c
> @@ -504,10 +504,17 @@ void *network_initializer(void *data)
>  		/*
>  		 * Check if the dry run flag is overwritten
>  		 */
> -		if (req->dry_run)
> +		switch (req->dry_run){
> +		case RUN_DRYRUN:
>  			software->globals.dry_run = 1;
> -		else
> +			break;
> +		case RUN_INSTALL:
>  			software->globals.dry_run = 0;
> +			break;
> +		case RUN_DEFAULT:
> +		default:
> +			software->globals.dry_run = software->globals.default_dry_run;

Hm, I'm a bit confused by the ternary option and this is probably due to
the bookkeeping with globals.dry_run and globals.*default*_dry_run:

Assume it stays boolean. If I set globals.dry_run = true, this is the
default to be applied in case the request doesn't overrule it:
(1) request's dry run is true
    → noop as both are true.
(2) request's dry run is false
    → conflict, which one to obey? False here then semantically means
      use the default as the request has not explicitly set it or
      explicitly set it but to false? Here one more bit to encode the
      wanted behavior does help.

If I set globals.dry_run = false, we again have two options:
(1) request's dry run is true
    → do dry run as request wants it explicitly.
(2) request's dry run is false
    → noop as both are false.

So, in essence, we do have to set the global dry run setting here
because we can't currently patch this through the chain and hence need
to modify the global setting while the current request is worked on.

Nonetheless, why don't we reset the global setting to its former value
at the end of the installation but instead keep it set until the next
request? In the meantime, globals.dry_run may have a different value
from globals.default_dry_run... 

Or am I on the wrong track here?



> +		}
>  
>  		/*
>  		 * Find the selection to be installed
> diff --git a/core/swupdate.c b/core/swupdate.c
> index 5099abd..0684de4 100644
> --- a/core/swupdate.c
> +++ b/core/swupdate.c
> @@ -390,6 +390,7 @@ static int install_from_file(char *fname, int check)
>  		save_state_string((char*)BOOTVAR_TRANSACTION, STATE_IN_PROGRESS);
>  	}
>  
> +	swcfg.globals.dry_run = swcfg.globals.default_dry_run;
>  	ret = install_images(&swcfg, fdsw, 1);
>  
>  	swupdate_progress_end(ret == 0 ? SUCCESS : FAILURE);
> @@ -799,7 +800,7 @@ int main(int argc, char **argv)
>  			loglevel = strtoul(optarg, NULL, 10);
>  			break;
>  		case 'n':
> -			swcfg.globals.dry_run = 1;
> +			swcfg.globals.default_dry_run = 1;
>  			break;
>  		case 'L':
>  			swcfg.globals.syslog_enabled = 1;
> diff --git a/doc/source/swupdate-ipc.rst b/doc/source/swupdate-ipc.rst
> index 31aa8d4..f506215 100644
> --- a/doc/source/swupdate-ipc.rst
> +++ b/doc/source/swupdate-ipc.rst
> @@ -105,7 +105,7 @@ the update process:
>          struct swupdate_request {
>                  unsigned int apiversion;
>                  sourcetype source;
> -                bool dry_run;
> +                int dry_run;
>                  size_t len;
>                  char info[512];
>                  char software_set[256];
> @@ -123,7 +123,7 @@ other fields as:
>  
>          - *sourcetype* : one of SOURCE_UNKNOWN, SOURCE_WEBSERVER,
>  	  SOURCE_SURICATTA, SOURCE_DOWNLOADER, SOURCE_LOCAL
> -        - *dry_run* : true if the update must run without installing on the hardware
> +        - *dry_run* : one of RUN_DEFAULT (set from command line), RUN_DRYRUN, RUN_INSTALL.
>          - *info, len* : a variable length data that can be forwarded to the progress
>            interface. The installer in SWUpdate does not evaluate it.
>          - *software_set* and *running_mode* : this allows to set the `selection` fot the update.
> diff --git a/include/network_ipc.h b/include/network_ipc.h
> index 2e6f75d..22ecb9a 100644
> --- a/include/network_ipc.h
> +++ b/include/network_ipc.h
> @@ -48,6 +48,12 @@ enum {
>  	CMD_ENABLE	/* Enable or disable suricatta mode */
>  };
>  
> +enum run_type {
> +	RUN_DEFAULT,
> +	RUN_DRYRUN,
> +	RUN_INSTALL
> +};
> +
>  #define SWUPDATE_API_VERSION 	0x1
>  /*
>   * Install structure to be filled before calling
> @@ -56,7 +62,7 @@ enum {
>  struct swupdate_request {
>  	unsigned int apiversion;
>  	sourcetype source;
> -	bool dry_run;
> +	enum run_type dry_run;
>  	size_t len;
>  	char info[512];
>  	char software_set[256];
> diff --git a/include/swupdate.h b/include/swupdate.h
> index 2b554b6..720868c 100644
> --- a/include/swupdate.h
> +++ b/include/swupdate.h
> @@ -137,6 +137,7 @@ struct swupdate_global_cfg {
>  	char preupdatecmd[SWUPDATE_GENERAL_STRING_SIZE];
>  	char default_software_set[SWUPDATE_GENERAL_STRING_SIZE];
>  	char default_running_mode[SWUPDATE_GENERAL_STRING_SIZE];
> +	int  default_dry_run;
>  	char minimum_version[SWUPDATE_GENERAL_STRING_SIZE];
>  	char current_version[SWUPDATE_GENERAL_STRING_SIZE];
>  	int cert_purpose;
> diff --git a/ipc/network_ipc-if.c b/ipc/network_ipc-if.c
> index fb59339..f09c417 100644
> --- a/ipc/network_ipc-if.c
> +++ b/ipc/network_ipc-if.c
> @@ -177,5 +177,6 @@ void swupdate_prepare_req(struct swupdate_request *req) {
>  		return;
>  	memset(req, 0, sizeof(struct swupdate_request));
>  	req->apiversion = SWUPDATE_API_VERSION;
> +	req->dry_run = RUN_DEFAULT;
>  	return;
>  }
> diff --git a/tools/swupdate-client.c b/tools/swupdate-client.c
> index f6bff6b..3e29bad 100644
> --- a/tools/swupdate-client.c
> +++ b/tools/swupdate-client.c
> @@ -134,7 +134,8 @@ static int send_file(const char* filename) {
>  
>  	struct swupdate_request req;
>  	swupdate_prepare_req(&req);
> -	req.dry_run = dry_run;
> +	if (dry_run)
> +		req.dry_run = RUN_DRYRUN;
>  	if (software_set && strlen(software_set)) {
>  		strncpy(req.software_set, software_set, sizeof(req.software_set) - 1);
>  		strncpy(req.running_mode, running_mode, sizeof(req.running_mode) - 1);
> -- 
> 2.25.1
> 


Kind regards,
   Christian
Stefano Babic Nov. 23, 2020, 12:26 p.m. UTC | #2
Hi Christian,

On 23.11.20 13:05, Christian Storm wrote:
> Hi Stefano,
> 
>> An IPC request can contain if the install should run in dry-run mode,
>> but this overwrites the same option issued with command line parameter.
>> Store --dry-run into SWUpdate's structure and use it if the request does
>> not have set any value for dry-run. A request should indicate if dry-run
>> is set or if the default value (from --dry-run) should be taken.
>>
>> Signed-off-by: Stefano Babic <sbabic@denx.de>
>> ---
>>  core/stream_interface.c     | 11 +++++++++--
>>  core/swupdate.c             |  3 ++-
>>  doc/source/swupdate-ipc.rst |  4 ++--
>>  include/network_ipc.h       |  8 +++++++-
>>  include/swupdate.h          |  1 +
>>  ipc/network_ipc-if.c        |  1 +
>>  tools/swupdate-client.c     |  3 ++-
>>  7 files changed, 24 insertions(+), 7 deletions(-)
>>
>> diff --git a/core/stream_interface.c b/core/stream_interface.c
>> index 3f8a168..39fa64e 100644
>> --- a/core/stream_interface.c
>> +++ b/core/stream_interface.c
>> @@ -504,10 +504,17 @@ void *network_initializer(void *data)
>>  		/*
>>  		 * Check if the dry run flag is overwritten
>>  		 */
>> -		if (req->dry_run)
>> +		switch (req->dry_run){
>> +		case RUN_DRYRUN:
>>  			software->globals.dry_run = 1;
>> -		else
>> +			break;
>> +		case RUN_INSTALL:
>>  			software->globals.dry_run = 0;
>> +			break;
>> +		case RUN_DEFAULT:
>> +		default:
>> +			software->globals.dry_run = software->globals.default_dry_run;
> 
> Hm, I'm a bit confused by the ternary option and this is probably due to
> the bookkeeping with globals.dry_run and globals.*default*_dry_run:
> 
> Assume it stays boolean.

I came to the conclusion that the request is not boolean. You have three
cases:

- set explicitely in the request true or false.
- dunno, that is the request is please install with the dry-run option
set when swupdate is started. A requester cannot know, and in the
request the dry-run option is in the third state "unset".

> If I set globals.dry_run = true, this is the
> default to be applied in case the request doesn't overrule it:
> (1) request's dry run is true
>     → noop as both are true.
> (2) request's dry run is false

No - request's dry run can be true, false or unset. Only if set, it
overrules the value at the startup. If not set, value of startup is
taken and can still be true or false.

If request's dry-run is set to false, then dry-run applies.

>     → conflict, which one to obey?

- request's dry run overrule command line --dry-run
- if request's is not set (RUN_DEFAULT), command line --dry-run is taken.

> False here then semantically means

That the reason I need an enum instead of a boolean. It is not a boolean
anymore, else I go into conflicts.

>       use the default as the request has not explicitly set

Not set == RUN_DEFAULT (==0).

> it or
>       explicitly set it but to false? Here one more bit to encode the
>       wanted behavior does help.
> 
> If I set globals.dry_run = false, we again have two options:
> (1) request's dry run is true
>     → do dry run as request wants it explicitly.
> (2) request's dry run is false
>     → noop as both are false.

But you can sumarize as:
	- request's dry run has priority
	- if request's dry-run is not set, default dry-run is taken.

> 
> So, in essence, we do have to set the global dry run setting here
> because we can't currently patch this through the chain and hence need
> to modify the global setting while the current request is worked on.
> 
> Nonetheless, why don't we reset the global setting to its former value
> at the end of the installation

Because we do not need it. The global setting dry-run is *always* set
before a run, and resetting at the end is not needed.

> but instead keep it set until the next
> request? In the meantime, globals.dry_run may have a different value
> from globals.default_dry_run... 

Yes, and ? Which is the issue then ?

Best regards,
Stefano

> 
> Or am I on the wrong track here?
> 
> 
> 
>> +		}
>>  
>>  		/*
>>  		 * Find the selection to be installed
>> diff --git a/core/swupdate.c b/core/swupdate.c
>> index 5099abd..0684de4 100644
>> --- a/core/swupdate.c
>> +++ b/core/swupdate.c
>> @@ -390,6 +390,7 @@ static int install_from_file(char *fname, int check)
>>  		save_state_string((char*)BOOTVAR_TRANSACTION, STATE_IN_PROGRESS);
>>  	}
>>  
>> +	swcfg.globals.dry_run = swcfg.globals.default_dry_run;
>>  	ret = install_images(&swcfg, fdsw, 1);
>>  
>>  	swupdate_progress_end(ret == 0 ? SUCCESS : FAILURE);
>> @@ -799,7 +800,7 @@ int main(int argc, char **argv)
>>  			loglevel = strtoul(optarg, NULL, 10);
>>  			break;
>>  		case 'n':
>> -			swcfg.globals.dry_run = 1;
>> +			swcfg.globals.default_dry_run = 1;
>>  			break;
>>  		case 'L':
>>  			swcfg.globals.syslog_enabled = 1;
>> diff --git a/doc/source/swupdate-ipc.rst b/doc/source/swupdate-ipc.rst
>> index 31aa8d4..f506215 100644
>> --- a/doc/source/swupdate-ipc.rst
>> +++ b/doc/source/swupdate-ipc.rst
>> @@ -105,7 +105,7 @@ the update process:
>>          struct swupdate_request {
>>                  unsigned int apiversion;
>>                  sourcetype source;
>> -                bool dry_run;
>> +                int dry_run;
>>                  size_t len;
>>                  char info[512];
>>                  char software_set[256];
>> @@ -123,7 +123,7 @@ other fields as:
>>  
>>          - *sourcetype* : one of SOURCE_UNKNOWN, SOURCE_WEBSERVER,
>>  	  SOURCE_SURICATTA, SOURCE_DOWNLOADER, SOURCE_LOCAL
>> -        - *dry_run* : true if the update must run without installing on the hardware
>> +        - *dry_run* : one of RUN_DEFAULT (set from command line), RUN_DRYRUN, RUN_INSTALL.
>>          - *info, len* : a variable length data that can be forwarded to the progress
>>            interface. The installer in SWUpdate does not evaluate it.
>>          - *software_set* and *running_mode* : this allows to set the `selection` fot the update.
>> diff --git a/include/network_ipc.h b/include/network_ipc.h
>> index 2e6f75d..22ecb9a 100644
>> --- a/include/network_ipc.h
>> +++ b/include/network_ipc.h
>> @@ -48,6 +48,12 @@ enum {
>>  	CMD_ENABLE	/* Enable or disable suricatta mode */
>>  };
>>  
>> +enum run_type {
>> +	RUN_DEFAULT,
>> +	RUN_DRYRUN,
>> +	RUN_INSTALL
>> +};
>> +
>>  #define SWUPDATE_API_VERSION 	0x1
>>  /*
>>   * Install structure to be filled before calling
>> @@ -56,7 +62,7 @@ enum {
>>  struct swupdate_request {
>>  	unsigned int apiversion;
>>  	sourcetype source;
>> -	bool dry_run;
>> +	enum run_type dry_run;
>>  	size_t len;
>>  	char info[512];
>>  	char software_set[256];
>> diff --git a/include/swupdate.h b/include/swupdate.h
>> index 2b554b6..720868c 100644
>> --- a/include/swupdate.h
>> +++ b/include/swupdate.h
>> @@ -137,6 +137,7 @@ struct swupdate_global_cfg {
>>  	char preupdatecmd[SWUPDATE_GENERAL_STRING_SIZE];
>>  	char default_software_set[SWUPDATE_GENERAL_STRING_SIZE];
>>  	char default_running_mode[SWUPDATE_GENERAL_STRING_SIZE];
>> +	int  default_dry_run;
>>  	char minimum_version[SWUPDATE_GENERAL_STRING_SIZE];
>>  	char current_version[SWUPDATE_GENERAL_STRING_SIZE];
>>  	int cert_purpose;
>> diff --git a/ipc/network_ipc-if.c b/ipc/network_ipc-if.c
>> index fb59339..f09c417 100644
>> --- a/ipc/network_ipc-if.c
>> +++ b/ipc/network_ipc-if.c
>> @@ -177,5 +177,6 @@ void swupdate_prepare_req(struct swupdate_request *req) {
>>  		return;
>>  	memset(req, 0, sizeof(struct swupdate_request));
>>  	req->apiversion = SWUPDATE_API_VERSION;
>> +	req->dry_run = RUN_DEFAULT;
>>  	return;
>>  }
>> diff --git a/tools/swupdate-client.c b/tools/swupdate-client.c
>> index f6bff6b..3e29bad 100644
>> --- a/tools/swupdate-client.c
>> +++ b/tools/swupdate-client.c
>> @@ -134,7 +134,8 @@ static int send_file(const char* filename) {
>>  
>>  	struct swupdate_request req;
>>  	swupdate_prepare_req(&req);
>> -	req.dry_run = dry_run;
>> +	if (dry_run)
>> +		req.dry_run = RUN_DRYRUN;
>>  	if (software_set && strlen(software_set)) {
>>  		strncpy(req.software_set, software_set, sizeof(req.software_set) - 1);
>>  		strncpy(req.running_mode, running_mode, sizeof(req.running_mode) - 1);
>> -- 
>> 2.25.1
>>
> 
> 
> Kind regards,
>    Christian
>
Storm, Christian Nov. 23, 2020, 1:15 p.m. UTC | #3
Hi Stefano,

> >> An IPC request can contain if the install should run in dry-run mode,
> >> but this overwrites the same option issued with command line parameter.
> >> Store --dry-run into SWUpdate's structure and use it if the request does
> >> not have set any value for dry-run. A request should indicate if dry-run
> >> is set or if the default value (from --dry-run) should be taken.
> >>
> >> Signed-off-by: Stefano Babic <sbabic@denx.de>
> >> ---
> >>  core/stream_interface.c     | 11 +++++++++--
> >>  core/swupdate.c             |  3 ++-
> >>  doc/source/swupdate-ipc.rst |  4 ++--
> >>  include/network_ipc.h       |  8 +++++++-
> >>  include/swupdate.h          |  1 +
> >>  ipc/network_ipc-if.c        |  1 +
> >>  tools/swupdate-client.c     |  3 ++-
> >>  7 files changed, 24 insertions(+), 7 deletions(-)
> >>
> >> diff --git a/core/stream_interface.c b/core/stream_interface.c
> >> index 3f8a168..39fa64e 100644
> >> --- a/core/stream_interface.c
> >> +++ b/core/stream_interface.c
> >> @@ -504,10 +504,17 @@ void *network_initializer(void *data)
> >>  		/*
> >>  		 * Check if the dry run flag is overwritten
> >>  		 */
> >> -		if (req->dry_run)
> >> +		switch (req->dry_run){
> >> +		case RUN_DRYRUN:
> >>  			software->globals.dry_run = 1;
> >> -		else
> >> +			break;
> >> +		case RUN_INSTALL:
> >>  			software->globals.dry_run = 0;
> >> +			break;
> >> +		case RUN_DEFAULT:
> >> +		default:
> >> +			software->globals.dry_run = software->globals.default_dry_run;
> > 
> > Hm, I'm a bit confused by the ternary option and this is probably due to
> > the bookkeeping with globals.dry_run and globals.*default*_dry_run:
> > 
> > Assume it stays boolean.
> 
> I came to the conclusion that the request is not boolean. You have three
> cases:
> 
> - set explicitely in the request true or false.
> - dunno, that is the request is please install with the dry-run option
> set when swupdate is started. A requester cannot know, and in the
> request the dry-run option is in the third state "unset".
> 
> > If I set globals.dry_run = true, this is the
> > default to be applied in case the request doesn't overrule it:
> > (1) request's dry run is true
> >     → noop as both are true.
> > (2) request's dry run is false
> 
> No - request's dry run can be true, false or unset. Only if set, it
> overrules the value at the startup. If not set, value of startup is
> taken and can still be true or false.
> 
> If request's dry-run is set to false, then dry-run applies.
> 
> >     → conflict, which one to obey?
> 
> - request's dry run overrule command line --dry-run
> - if request's is not set (RUN_DEFAULT), command line --dry-run is taken.
> 
> > False here then semantically means
> 
> That the reason I need an enum instead of a boolean. It is not a boolean
> anymore, else I go into conflicts.

Yes, question here is how to resolve it and this is what I wanted to
point out/question... In essence, with boolean, you can't distinguish
between (1) 'false' meaning not explicitly set or (2) explicitly set to
'false'. Understood.


> >       use the default as the request has not explicitly set
> 
> Not set == RUN_DEFAULT (==0).
> 
> > it or
> >       explicitly set it but to false? Here one more bit to encode the
> >       wanted behavior does help.
> > 
> > If I set globals.dry_run = false, we again have two options:
> > (1) request's dry run is true
> >     → do dry run as request wants it explicitly.
> > (2) request's dry run is false
> >     → noop as both are false.
> 
> But you can sumarize as:
> 	- request's dry run has priority
> 	- if request's dry-run is not set, default dry-run is taken.

Yes, agreed.


> > So, in essence, we do have to set the global dry run setting here
> > because we can't currently patch this through the chain and hence need
> > to modify the global setting while the current request is worked on.
> > 
> > Nonetheless, why don't we reset the global setting to its former value
> > at the end of the installation
> 
> Because we do not need it. The global setting dry-run is *always* set
> before a run, and resetting at the end is not needed.
> 
> > but instead keep it set until the next
> > request? In the meantime, globals.dry_run may have a different value
> > from globals.default_dry_run... 
> 
> Yes, and ? Which is the issue then ?

No concrete issue, just wanted to unterstand whether I'm off-track here
as I assumed a reset to the global dry run value prior to the current
request is due after the request has been finished and hence wrote the
patches accordingly. So, with this discussion, your comment

"run->dry_run and software->globals.dry_run are used, but the they are not
 interchangeable. I sent a V2 for this."

actually makes more sense and I do see the point in your V2 patch

  '[PATCH V2] Don't set (persistent) state in dry run mode'

:) Thanks!


Kind regards,
   Christian
diff mbox series

Patch

diff --git a/core/stream_interface.c b/core/stream_interface.c
index 3f8a168..39fa64e 100644
--- a/core/stream_interface.c
+++ b/core/stream_interface.c
@@ -504,10 +504,17 @@  void *network_initializer(void *data)
 		/*
 		 * Check if the dry run flag is overwritten
 		 */
-		if (req->dry_run)
+		switch (req->dry_run){
+		case RUN_DRYRUN:
 			software->globals.dry_run = 1;
-		else
+			break;
+		case RUN_INSTALL:
 			software->globals.dry_run = 0;
+			break;
+		case RUN_DEFAULT:
+		default:
+			software->globals.dry_run = software->globals.default_dry_run;
+		}
 
 		/*
 		 * Find the selection to be installed
diff --git a/core/swupdate.c b/core/swupdate.c
index 5099abd..0684de4 100644
--- a/core/swupdate.c
+++ b/core/swupdate.c
@@ -390,6 +390,7 @@  static int install_from_file(char *fname, int check)
 		save_state_string((char*)BOOTVAR_TRANSACTION, STATE_IN_PROGRESS);
 	}
 
+	swcfg.globals.dry_run = swcfg.globals.default_dry_run;
 	ret = install_images(&swcfg, fdsw, 1);
 
 	swupdate_progress_end(ret == 0 ? SUCCESS : FAILURE);
@@ -799,7 +800,7 @@  int main(int argc, char **argv)
 			loglevel = strtoul(optarg, NULL, 10);
 			break;
 		case 'n':
-			swcfg.globals.dry_run = 1;
+			swcfg.globals.default_dry_run = 1;
 			break;
 		case 'L':
 			swcfg.globals.syslog_enabled = 1;
diff --git a/doc/source/swupdate-ipc.rst b/doc/source/swupdate-ipc.rst
index 31aa8d4..f506215 100644
--- a/doc/source/swupdate-ipc.rst
+++ b/doc/source/swupdate-ipc.rst
@@ -105,7 +105,7 @@  the update process:
         struct swupdate_request {
                 unsigned int apiversion;
                 sourcetype source;
-                bool dry_run;
+                int dry_run;
                 size_t len;
                 char info[512];
                 char software_set[256];
@@ -123,7 +123,7 @@  other fields as:
 
         - *sourcetype* : one of SOURCE_UNKNOWN, SOURCE_WEBSERVER,
 	  SOURCE_SURICATTA, SOURCE_DOWNLOADER, SOURCE_LOCAL
-        - *dry_run* : true if the update must run without installing on the hardware
+        - *dry_run* : one of RUN_DEFAULT (set from command line), RUN_DRYRUN, RUN_INSTALL.
         - *info, len* : a variable length data that can be forwarded to the progress
           interface. The installer in SWUpdate does not evaluate it.
         - *software_set* and *running_mode* : this allows to set the `selection` fot the update.
diff --git a/include/network_ipc.h b/include/network_ipc.h
index 2e6f75d..22ecb9a 100644
--- a/include/network_ipc.h
+++ b/include/network_ipc.h
@@ -48,6 +48,12 @@  enum {
 	CMD_ENABLE	/* Enable or disable suricatta mode */
 };
 
+enum run_type {
+	RUN_DEFAULT,
+	RUN_DRYRUN,
+	RUN_INSTALL
+};
+
 #define SWUPDATE_API_VERSION 	0x1
 /*
  * Install structure to be filled before calling
@@ -56,7 +62,7 @@  enum {
 struct swupdate_request {
 	unsigned int apiversion;
 	sourcetype source;
-	bool dry_run;
+	enum run_type dry_run;
 	size_t len;
 	char info[512];
 	char software_set[256];
diff --git a/include/swupdate.h b/include/swupdate.h
index 2b554b6..720868c 100644
--- a/include/swupdate.h
+++ b/include/swupdate.h
@@ -137,6 +137,7 @@  struct swupdate_global_cfg {
 	char preupdatecmd[SWUPDATE_GENERAL_STRING_SIZE];
 	char default_software_set[SWUPDATE_GENERAL_STRING_SIZE];
 	char default_running_mode[SWUPDATE_GENERAL_STRING_SIZE];
+	int  default_dry_run;
 	char minimum_version[SWUPDATE_GENERAL_STRING_SIZE];
 	char current_version[SWUPDATE_GENERAL_STRING_SIZE];
 	int cert_purpose;
diff --git a/ipc/network_ipc-if.c b/ipc/network_ipc-if.c
index fb59339..f09c417 100644
--- a/ipc/network_ipc-if.c
+++ b/ipc/network_ipc-if.c
@@ -177,5 +177,6 @@  void swupdate_prepare_req(struct swupdate_request *req) {
 		return;
 	memset(req, 0, sizeof(struct swupdate_request));
 	req->apiversion = SWUPDATE_API_VERSION;
+	req->dry_run = RUN_DEFAULT;
 	return;
 }
diff --git a/tools/swupdate-client.c b/tools/swupdate-client.c
index f6bff6b..3e29bad 100644
--- a/tools/swupdate-client.c
+++ b/tools/swupdate-client.c
@@ -134,7 +134,8 @@  static int send_file(const char* filename) {
 
 	struct swupdate_request req;
 	swupdate_prepare_req(&req);
-	req.dry_run = dry_run;
+	if (dry_run)
+		req.dry_run = RUN_DRYRUN;
 	if (software_set && strlen(software_set)) {
 		strncpy(req.software_set, software_set, sizeof(req.software_set) - 1);
 		strncpy(req.running_mode, running_mode, sizeof(req.running_mode) - 1);