-
Notifications
You must be signed in to change notification settings - Fork 651
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add local.instance.bridged
setting.
#3193
Conversation
Codecov Report
@@ Coverage Diff @@
## add-network-bridges #3193 +/- ##
=======================================================
- Coverage 88.56% 88.53% -0.04%
=======================================================
Files 239 239
Lines 12123 12143 +20
=======================================================
+ Hits 10737 10751 +14
- Misses 1386 1392 +6
|
f1d86ea
to
712df61
Compare
4a943ee
to
eb421ee
Compare
48ac4cd
to
42bf8ec
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @luis4a0, I was curious and I just had a quick look. The code looks good, I like that you're splitting things into small self contained units 👍 I spotted only a couple of wrinkles in this very superficial pass.
@@ -153,6 +154,48 @@ void update_disk(const QString& key, const QString& val, mp::VirtualMachine& ins | |||
} | |||
} | |||
|
|||
bool to_bool(const QString& key, const QString& val) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is implemented in BoolSettingSpec
. Instead of copy+pasting from there, why don't you instantiate a helper object and use that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @ricab, thanks for your quick review!
I thought in avoid copy+pasting, but I opted for not a QString
and comparing against it. Just true or false. Do you still think it's OK to reuse the existing implementation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see what you mean: you want to return a bool
and compare against that in the code, right? But you can still achieve that with an extra step. For example, just something like this to replace the contents of to_bool
: return BoolSettingSpec{key, "false"}.interpret(val) == "true";
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to avoid that string comparison, and throw directly instead of returning a value before throwing. But well, it is true that the code looks much better the way you propose. Since time is not critical here, I changed it. Thanks!
auto size = get_memory_size(key, val); | ||
if (property == mem_suffix) | ||
update_mem(key, val, instance, spec, size); | ||
if (property == bridged_suffix) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
else if
? To avoid one extra nesting level.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, changed. I was hesitating whether to mix an inline else if
with a structured else { stmt; if ... }
. But right, we save four columns the way you mention.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not for saving spaces, it's that it makes it easier to understand that they are alternatives at the same level, with no further shared logic (unlike the following 2 properties, which do share the conversion of the memory size).
42bf8ec
to
af6c565
Compare
eb421ee
to
57c464f
Compare
af6c565
to
b1c8d6b
Compare
inline static constexpr auto properties = std::array{"cpus", "disk", "memory"}; | ||
inline static constexpr auto numeric_properties = std::array{"cpus", "disk", "memory"}; | ||
inline static constexpr auto boolean_properties = std::array{"bridged"}; | ||
inline static constexpr auto properties = std::array{"cpus", "disk", "memory", "bridged"}; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know it stems from the original code, but maybe change the copy initialization to direct initialization to make the code cleaner.
inline static constexpr std::array numeric_properties{"cpus", "disk", "memory"};
inline static constexpr std::array boolean_properties{"bridged"};
inline static constexpr std::array properties{"cpus", "disk", "memory", "bridged"};
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, looks better that way. Changed.
return true; | ||
} | ||
|
||
return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
std algorithm based code can be another alternative, the code is shorter, the readability probably is the same
return std::any_of(spec.extra_interfaces.cbegin(), spec.extra_interfaces.cend(),
[](const auto& network) -> bool { return network.auto_mode; });
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks nice, thanks! Changed.
auto bridged = mp::BoolSettingSpec{key, "false"}.interpret(val) == "true"; | ||
|
||
if (!bridged && is_bridged(spec)) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to elaborate the roles of bridged boolean (it looks like is checking user's input) and is_bridged(spec) (looks like checking if the spec is bridged)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, sorry if it wasn't clear. The bridged
boolean is the value given by the user. The is_bridged()
function returns a boolean stating if the VM has a bridged interface.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, thanks.
// An extra interface in auto mode will result in bridging. | ||
specs[target_instance_name].extra_interfaces = {{"id", "52:54:00:12:34:56", bridged}}; | ||
|
||
auto got = make_handler().get(make_key(target_instance_name, "bridged")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const auto got
is better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, better. Changed.
HI @luis4a0 , it looks good overall. I just left a handful minor comments. |
b1c8d6b
to
ac54295
Compare
Hey @georgeliao, thanks for the review! I addressed your concerns, let me know if everything looks better now. |
bool is_bridged(const mp::VMSpecs& spec) | ||
{ | ||
return std::any_of(spec.extra_interfaces.cbegin(), spec.extra_interfaces.cend(), | ||
[](const auto& network) -> bool { return network.auto_mode; }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @luis4a0, I think for our purposes we'd better consider the instance bridged if and only if it has an extra_interface corresponding to the network that is currently set for local.bridged-network
. That would make it symmetric to launch --bridged
and allow adding multiple interfaces.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @ricab, thanks for your comment. You're right, I didn't think on that. I changed the code to reflect this behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great, thanks!
src/daemon/daemon.cpp
Outdated
|
||
if (bridged_id == "") | ||
{ | ||
throw std::runtime_error(fmt::format("You have to `multipass set {}=<name>` to use the `--bridged` shortcut.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
--bridged
is not applicable in the case of settings, so the message needs to be generalized. Perhaps just:
throw std::runtime_error(fmt::format("You have to `multipass set {}=<name>` to use the `--bridged` shortcut.", | |
throw std::runtime_error(fmt::format("You have to `multipass set {}=<name>` to use the "bridged" shortcut.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, changed.
src/daemon/daemon.cpp
Outdated
preparing_instances, [this] { persist_instances(); })} | ||
instance_mod_handler{register_instance_mod( | ||
vm_instance_specs, operative_instances, deleted_instances, preparing_instances, | ||
[this] { persist_instances(); }, [] { return get_bridged_interface_name(); })} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you really need the lambda here? Unlike to persist instances, there is no closure for the bridge, so you should be able to pass the function directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, nice catch. [this] { persist_instances(); }, get_bridged_interface_name)}
will do it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, changed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
It must return true if and only if there exists in the instance an interface bridged to the current interface set in local.bridged-interface.
957653f
to
1a28788
Compare
Hey @ricab @georgeliao, thanks for the review! Let me note that all the uncovered code corresponds to the |
Add `local.instance.bridged` setting.
Add `local.instance.bridged` setting.
Add `local.instance.bridged` setting.
Add `local.instance.bridged` setting.
Add `local.instance.bridged` setting.
Add `local.instance.bridged` setting.
Add `local.instance.bridged` setting.
Add `local.instance.bridged` setting.
Add `local.instance.bridged` setting.
Add `local.instance.bridged` setting.
Add `local.instance.bridged` setting.
Add `local.instance.bridged` setting.
Add `local.instance.bridged` setting.
This PR implements the
set
interface to add a bridged network to an existing instance.