7 #include <libvirt/libvirt.h>
8 #include <libvirt/virterror.h>
10 #include <linux/if_tun.h>
11 #include <boost/lexical_cast.hpp>
12 #include <boost/uuid/uuid_io.hpp>
13 #include <pugixml/pugixml.hpp>
23 using pugi::xml_document;
25 using pugi::xml_attribute;
26 using pugi::xml_parse_result;
31 while (close(fd) < 0) {
33 LOG(ERROR,
"Could not close descriptor, errno: " << errno);
43 LOG(DEBUG,
"Allocating TAP device " << devname);
45 while ((fd = open(
"/dev/net/tun", O_RDWR)) < 0) {
47 LOG(ERROR,
"Cannot open /dev/net/tun");
52 memset(&ifr, 0,
sizeof(ifr));
53 ifr.ifr_flags = flags;
54 strncpy(ifr.ifr_name, devname, IFNAMSIZ-1);
56 if (ioctl(fd, TUNSETIFF, (
void *)&ifr) < 0) {
58 LOG(ERROR,
"Error creating tap interface "
59 << devname <<
", errno: " << errno);
62 if (ioctl(fd, TUNSETPERSIST, 1) < 0) {
64 LOG(ERROR,
"Error setting persistent tap interface "
65 << devname <<
", errno: " << errno);
69 LOG(DEBUG,
"Created device: " << ifr.ifr_name);
71 ifr.ifr_flags = IFF_UP;
72 fd = socket(AF_INET, SOCK_DGRAM, 0);
74 LOG(ERROR,
"Could not open AF_INET socket, errno: " << errno);
77 ioctl(fd, SIOCSIFFLAGS, &ifr);
86 while ((fd = open(
"/dev/net/tun", O_RDWR)) < 0) {
88 LOG(ERROR,
"Cannot open /dev/net/tun");
93 memset(&ifr, 0,
sizeof(ifr));
94 ifr.ifr_flags = IFF_TAP;
95 strncpy(ifr.ifr_name, devname, IFNAMSIZ-1);
97 if (ioctl(fd, TUNSETIFF, (
void *)&ifr) < 0) {
99 LOG(ERROR,
"Error opening tap interface "
100 << devname <<
", errno: " << errno);
103 if (ioctl(fd, TUNSETPERSIST, 0) < 0) {
105 LOG(ERROR,
"Error destroying tap interface "
106 << devname <<
", errno: " << errno);
114 const std::string &child_name) {
115 xml_node child = parent->child(child_name.c_str());
118 return parent->append_child(child_name.c_str());
127 LOG(DEBUG,
"creating libvirt instance start task");
137 LOG(DEBUG,
"creating libvirt instance stop task");
146 LOG(DEBUG,
"checked whether libvirt is "
147 "applicable for chosen service instance");
154 std::string dom_uuid_str =
163 LOG(ERROR,
"Could not parse domain XML");
166 LOG(DEBUG,
"Creating domain: " << xml);
169 LOG(ERROR,
"Error creating TAP interfaces");
176 LOG(ERROR,
"Error creating domain: " << virGetLastErrorMessage());
182 LOG(DEBUG,
"Domain created: " << dom_uuid_str);
188 std::string dom_uuid_str =
189 boost::lexical_cast<std::string>(si_properties_.instance_id);
190 parent_adapter_->EnsureDestroyed(dom_uuid_str, si_properties_);
195 std::string dom_uuid_str =
196 boost::lexical_cast<std::string>(si_properties_.instance_id);
198 xml_document domain_xml_conf;
199 xml_parse_result parse_result =
200 domain_xml_conf.load(si_properties_.instance_data.c_str());
201 if (!parse_result || !domain_xml_conf.child(
"domain")) {
202 LOG(ERROR,
"Error parsing XML data or domain is missing");
207 xml_node devices_node = domain_xml_conf.child(
"domain").child(
"devices");
209 domain_xml_conf.child(
"domain").append_child(
"devices");
212 DomainXMLAssignUUID(dom_uuid_str, domain_xml_conf);
215 DomainXMLSetInterfaceData(domain_xml_conf, dom_uuid_str);
217 std::stringstream domain_conf;
218 domain_xml_conf.save(domain_conf);
219 return domain_conf.str();
223 const std::string &dom_uuid_str,
224 const xml_document &libvirt_xml_conf) {
225 xml_node domain_node = libvirt_xml_conf.child(
"domain");
228 if (name_node.text().empty())
229 name_node.text().set(
"contrail_si-");
230 uuid_node.text().set(dom_uuid_str.c_str());
231 name_node.text().set((std::string(name_node.text().get()) +
"-" +
232 dom_uuid_str.substr(0, 5)).c_str());
233 LOG(DEBUG, dom_uuid_str.c_str());
237 const std::string &dom_uuid) {
249 const xml_document &libvirt_xml_conf,
const std::string &dom_uuid) {
250 LOG(DEBUG,
"adding vrouter interface "
251 "data to libvirt instance configuration");
253 xml_node devices_node = libvirt_xml_conf.child(
"domain").child(
"devices");
255 DomainXMLAddInterface(&devices_node,
256 si_properties_.mac_addr_inside,
258 DomainXMLAddInterface(&devices_node,
259 si_properties_.mac_addr_outside,
261 DomainXMLAddInterface(&devices_node,
262 si_properties_.mac_addr_management,
267 xml_node *devices_node,
const std::string &mac_addr,
268 const std::string &intf_name) {
269 xml_node intf_node = devices_node->append_child(
"interface");
270 intf_node.append_attribute(
"type").set_value(
"ethernet");
272 xml_node mac_node = intf_node.append_child(
"mac");
273 mac_node.append_attribute(
"address").set_value(mac_addr.c_str());
275 xml_node target_node = intf_node.append_child(
"target");
276 target_node.append_attribute(
"dev").set_value(intf_name.c_str());
280 const std::string &dom_uuid,
char type) {
281 return std::string(
"tap_" + dom_uuid.substr(0, 8) +
type);
288 LOG(DEBUG,
"ensuring we have a libvirt connection");
298 const std::string &dom_uuid_str,
300 virDomainPtr dom = virDomainLookupByUUIDString(
conn_, dom_uuid_str.c_str());
302 std::string domain_name = std::string(virDomainGetName(dom));
303 virDomainDestroy(dom);
317 LOG(DEBUG,
"registering TAP interfaces to vrouter");
318 std::string dom_uuid_str =
319 boost::lexical_cast<std::string>(si_properties.
instance_id);
325 Ip4Address::from_string(
336 agent_->
cfg()->cfg_interface_client()->FetchInterfaceData(
353 agent_->
cfg()->cfg_interface_client()->FetchInterfaceData(
370 agent_->
cfg()->cfg_interface_client()->FetchInterfaceData(
402 LOG(DEBUG,
"closing libvirt connection");
404 virConnectClose(
conn_);
std::string mac_addr_management
std::string ip_addr_inside
LibvirtInstanceAdapter * parent_adapter_
static bool CreateTAPInterfaces(const std::string &dom_uuid)
InterfaceTable * interface_table() const
static std::string GenIntfName(const std::string &dom_uuid, char type)
InstanceTask * CreateStartTask(const ServiceInstance::Properties &props, bool update)
static void DomainXMLAddInterface(pugi::xml_node *devices_node, const std::string &mac_addr, const std::string &intf_name)
void DomainXMLSetInterfaceData(const pugi::xml_document &libvirt_xml_conf, const std::string &dom_uuid)
static tbb::mutex conn_mutex_
void EnsureDestroyed(const std::string &dom_uuid_str, const ServiceInstance::Properties &si_properties)
static bool close_descriptor(int fd)
std::string ip_addr_management
static const uint8_t vHostUserClient
static const uint32_t kInvalidVlanId
boost::asio::ip::address_v6 Ip6Address
boost::uuids::uuid instance_id
boost::uuids::uuid vmi_outside
boost::uuids::uuid vmi_management
static const std::string & NullString()
static xml_node get_or_create_node(xml_node *parent, const std::string &child_name)
bool RegisterInterfaces(const ServiceInstance::Properties &si_properties)
static bool alloc_tap_interface(const char *devname, int flags)
bool isApplicable(const ServiceInstance::Properties &props)
int vrouter_instance_type
std::string mac_addr_inside
static bool destroy_tap_interface(const char *devname)
#define LOG(_Level, _Msg)
static void DomainXMLAssignUUID(const std::string &libvirt_conf_str, const pugi::xml_document &libvirt_xml_conf)
void UnregisterInterfaces(const ServiceInstance::Properties &si_properties)
AgentConfig * cfg() const
~LibvirtInstanceAdapter()
boost::uuids::uuid vmi_inside
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)
std::string mac_addr_outside
InstanceTask * CreateStopTask(const ServiceInstance::Properties &props)
const ServiceInstance::Properties & si_properties_
std::string libvirt_conn_addr_
std::string ip_addr_outside