11 #include <libvirt/libvirt.h>
12 #include <libvirt/virterror.h>
14 #include <linux/if_tun.h>
15 #include <boost/lexical_cast.hpp>
16 #include <boost/uuid/uuid_io.hpp>
17 #include <pugixml/pugixml.hpp>
25 using pugi::xml_document;
27 using pugi::xml_attribute;
28 using pugi::xml_parse_result;
33 while (close(fd) < 0) {
35 LOG(ERROR,
"Could not close descriptor, errno: " << errno);
45 LOG(DEBUG,
"Allocating TAP device " << devname);
47 while ((fd = open(
"/dev/net/tun", O_RDWR)) < 0) {
49 LOG(ERROR,
"Cannot open /dev/net/tun");
54 memset(&ifr, 0,
sizeof(ifr));
55 ifr.ifr_flags = flags;
56 strncpy(ifr.ifr_name, devname, IFNAMSIZ-1);
58 if (ioctl(fd, TUNSETIFF, (
void *)&ifr) < 0) {
60 LOG(ERROR,
"Error creating tap interface "
61 << devname <<
", errno: " << errno);
64 if (ioctl(fd, TUNSETPERSIST, 1) < 0) {
66 LOG(ERROR,
"Error setting persistent tap interface "
67 << devname <<
", errno: " << errno);
71 LOG(DEBUG,
"Created device: " << ifr.ifr_name);
73 ifr.ifr_flags = IFF_UP;
74 fd = socket(AF_INET, SOCK_DGRAM, 0);
76 LOG(ERROR,
"Could not open AF_INET socket, errno: " << errno);
79 ioctl(fd, SIOCSIFFLAGS, &ifr);
88 while ((fd = open(
"/dev/net/tun", O_RDWR)) < 0) {
90 LOG(ERROR,
"Cannot open /dev/net/tun");
95 memset(&ifr, 0,
sizeof(ifr));
96 ifr.ifr_flags = IFF_TAP;
97 strncpy(ifr.ifr_name, devname, IFNAMSIZ-1);
99 if (ioctl(fd, TUNSETIFF, (
void *)&ifr) < 0) {
101 LOG(ERROR,
"Error opening tap interface "
102 << devname <<
", errno: " << errno);
105 if (ioctl(fd, TUNSETPERSIST, 0) < 0) {
107 LOG(ERROR,
"Error destroying tap interface "
108 << devname <<
", errno: " << errno);
116 const std::string &child_name) {
117 xml_node child = parent->child(child_name.c_str());
120 return parent->append_child(child_name.c_str());
129 LOG(DEBUG,
"creating libvirt instance start task");
139 LOG(DEBUG,
"creating libvirt instance stop task");
148 LOG(DEBUG,
"checked whether libvirt is "
149 "applicable for chosen service instance");
156 std::string dom_uuid_str =
165 LOG(ERROR,
"Could not parse domain XML");
168 LOG(DEBUG,
"Creating domain: " << xml);
171 LOG(ERROR,
"Error creating TAP interfaces");
178 LOG(ERROR,
"Error creating domain: " << virGetLastErrorMessage());
184 LOG(DEBUG,
"Domain created: " << dom_uuid_str);
190 std::string dom_uuid_str =
191 boost::lexical_cast<std::string>(si_properties_.instance_id);
192 parent_adapter_->EnsureDestroyed(dom_uuid_str, si_properties_);
197 std::string dom_uuid_str =
198 boost::lexical_cast<std::string>(si_properties_.instance_id);
200 xml_document domain_xml_conf;
201 xml_parse_result parse_result =
202 domain_xml_conf.load_string(si_properties_.instance_data.c_str());
203 if (!parse_result || !domain_xml_conf.child(
"domain")) {
204 LOG(ERROR,
"Error parsing XML data or domain is missing");
209 xml_node devices_node = domain_xml_conf.child(
"domain").child(
"devices");
211 domain_xml_conf.child(
"domain").append_child(
"devices");
214 DomainXMLAssignUUID(dom_uuid_str, domain_xml_conf);
217 DomainXMLSetInterfaceData(domain_xml_conf, dom_uuid_str);
219 std::stringstream domain_conf;
220 domain_xml_conf.save(domain_conf);
221 return domain_conf.str();
225 const std::string &dom_uuid_str,
226 const xml_document &libvirt_xml_conf) {
227 xml_node domain_node = libvirt_xml_conf.child(
"domain");
230 if (name_node.text().empty())
231 name_node.text().set(
"contrail_si-");
232 uuid_node.text().set(dom_uuid_str.c_str());
233 name_node.text().set((std::string(name_node.text().get()) +
"-" +
234 dom_uuid_str.substr(0, 5)).c_str());
235 LOG(DEBUG, dom_uuid_str.c_str());
239 const std::string &dom_uuid) {
251 const xml_document &libvirt_xml_conf,
const std::string &dom_uuid) {
252 LOG(DEBUG,
"adding vrouter interface "
253 "data to libvirt instance configuration");
255 xml_node devices_node = libvirt_xml_conf.child(
"domain").child(
"devices");
257 DomainXMLAddInterface(&devices_node,
258 si_properties_.mac_addr_inside,
260 DomainXMLAddInterface(&devices_node,
261 si_properties_.mac_addr_outside,
263 DomainXMLAddInterface(&devices_node,
264 si_properties_.mac_addr_management,
269 xml_node *devices_node,
const std::string &mac_addr,
270 const std::string &intf_name) {
271 xml_node intf_node = devices_node->append_child(
"interface");
272 intf_node.append_attribute(
"type").set_value(
"ethernet");
274 xml_node mac_node = intf_node.append_child(
"mac");
275 mac_node.append_attribute(
"address").set_value(mac_addr.c_str());
277 xml_node target_node = intf_node.append_child(
"target");
278 target_node.append_attribute(
"dev").set_value(intf_name.c_str());
282 const std::string &dom_uuid,
char type) {
283 return std::string(
"tap_" + dom_uuid.substr(0, 8) +
type);
290 LOG(DEBUG,
"ensuring we have a libvirt connection");
300 const std::string &dom_uuid_str,
302 virDomainPtr dom = virDomainLookupByUUIDString(
conn_, dom_uuid_str.c_str());
304 std::string domain_name = std::string(virDomainGetName(dom));
305 virDomainDestroy(dom);
319 LOG(DEBUG,
"registering TAP interfaces to vrouter");
320 std::string dom_uuid_str =
321 boost::lexical_cast<std::string>(si_properties.
instance_id);
327 Ip4Address::from_string(
338 agent_->
cfg()->cfg_interface_client()->FetchInterfaceData(
355 agent_->
cfg()->cfg_interface_client()->FetchInterfaceData(
372 agent_->
cfg()->cfg_interface_client()->FetchInterfaceData(
404 LOG(DEBUG,
"closing libvirt connection");
406 virConnectClose(
conn_);
boost::asio::ip::address_v6 Ip6Address
InterfaceTable * interface_table() const
AgentConfig * cfg() const
static const std::string & NullString()
const ServiceInstance::Properties & si_properties_
void DomainXMLSetInterfaceData(const pugi::xml_document &libvirt_xml_conf, const std::string &dom_uuid)
LibvirtInstanceAdapter * parent_adapter_
static bool CreateTAPInterfaces(const std::string &dom_uuid)
static void DomainXMLAddInterface(pugi::xml_node *devices_node, const std::string &mac_addr, const std::string &intf_name)
static void DomainXMLAssignUUID(const std::string &libvirt_conf_str, const pugi::xml_document &libvirt_xml_conf)
~LibvirtInstanceAdapter()
bool isApplicable(const ServiceInstance::Properties &props)
bool RegisterInterfaces(const ServiceInstance::Properties &si_properties)
InstanceTask * CreateStopTask(const ServiceInstance::Properties &props)
void EnsureDestroyed(const std::string &dom_uuid_str, const ServiceInstance::Properties &si_properties)
std::string libvirt_conn_addr_
static std::mutex conn_mutex_
static std::string GenIntfName(const std::string &dom_uuid, char type)
InstanceTask * CreateStartTask(const ServiceInstance::Properties &props, bool update)
void UnregisterInterfaces(const ServiceInstance::Properties &si_properties)
static void NovaAdd(InterfaceTable *table, const boost::uuids::uuid &intf_uuid, const std::string &os_name, const Ip4Address &addr, const std::string &mac, const std::string &vn_name, const boost::uuids::uuid &vm_project_uuid, uint16_t tx_vlan_id, uint16_t rx_vlan_id, const std::string &parent, const Ip6Address &ipv6, uint8_t vhostuser_mode, Interface::Transport transport, uint8_t link_state)
static const uint32_t kInvalidVlanId
static const uint8_t vHostUserClient
static bool close_descriptor(int fd)
static xml_node get_or_create_node(xml_node *parent, const std::string &child_name)
static bool destroy_tap_interface(const char *devname)
static bool alloc_tap_interface(const char *devname, int flags)
#define LOG(_Level, _Msg)
boost::uuids::uuid vmi_inside
int vrouter_instance_type
std::string ip_addr_inside
std::string mac_addr_outside
boost::uuids::uuid instance_id
boost::uuids::uuid vmi_management
std::string mac_addr_inside
boost::uuids::uuid vmi_outside
std::string ip_addr_outside
std::string mac_addr_management
std::string ip_addr_management